.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * Processor capabilities determination functions. |
---|
3 | 4 | * |
---|
.. | .. |
---|
5 | 6 | * Copyright (C) 1994 - 2006 Ralf Baechle |
---|
6 | 7 | * Copyright (C) 2003, 2004 Maciej W. Rozycki |
---|
7 | 8 | * Copyright (C) 2001, 2004, 2011, 2012 MIPS Technologies, Inc. |
---|
8 | | - * |
---|
9 | | - * This program is free software; you can redistribute it and/or |
---|
10 | | - * modify it under the terms of the GNU General Public License |
---|
11 | | - * as published by the Free Software Foundation; either version |
---|
12 | | - * 2 of the License, or (at your option) any later version. |
---|
13 | 9 | */ |
---|
14 | 10 | #include <linux/init.h> |
---|
15 | 11 | #include <linux/kernel.h> |
---|
.. | .. |
---|
32 | 28 | #include <asm/spram.h> |
---|
33 | 29 | #include <linux/uaccess.h> |
---|
34 | 30 | |
---|
| 31 | +#include "fpu-probe.h" |
---|
| 32 | + |
---|
| 33 | +#include <asm/mach-loongson64/cpucfg-emul.h> |
---|
| 34 | + |
---|
35 | 35 | /* Hardware capabilities */ |
---|
36 | 36 | unsigned int elf_hwcap __read_mostly; |
---|
37 | 37 | EXPORT_SYMBOL_GPL(elf_hwcap); |
---|
38 | | - |
---|
39 | | -/* |
---|
40 | | - * Get the FPU Implementation/Revision. |
---|
41 | | - */ |
---|
42 | | -static inline unsigned long cpu_get_fpu_id(void) |
---|
43 | | -{ |
---|
44 | | - unsigned long tmp, fpu_id; |
---|
45 | | - |
---|
46 | | - tmp = read_c0_status(); |
---|
47 | | - __enable_fpu(FPU_AS_IS); |
---|
48 | | - fpu_id = read_32bit_cp1_register(CP1_REVISION); |
---|
49 | | - write_c0_status(tmp); |
---|
50 | | - return fpu_id; |
---|
51 | | -} |
---|
52 | | - |
---|
53 | | -/* |
---|
54 | | - * Check if the CPU has an external FPU. |
---|
55 | | - */ |
---|
56 | | -static inline int __cpu_has_fpu(void) |
---|
57 | | -{ |
---|
58 | | - return (cpu_get_fpu_id() & FPIR_IMP_MASK) != FPIR_IMP_NONE; |
---|
59 | | -} |
---|
60 | 38 | |
---|
61 | 39 | static inline unsigned long cpu_get_msa_id(void) |
---|
62 | 40 | { |
---|
.. | .. |
---|
70 | 48 | write_c0_status(status); |
---|
71 | 49 | return msa_id; |
---|
72 | 50 | } |
---|
73 | | - |
---|
74 | | -/* |
---|
75 | | - * Determine the FCSR mask for FPU hardware. |
---|
76 | | - */ |
---|
77 | | -static inline void cpu_set_fpu_fcsr_mask(struct cpuinfo_mips *c) |
---|
78 | | -{ |
---|
79 | | - unsigned long sr, mask, fcsr, fcsr0, fcsr1; |
---|
80 | | - |
---|
81 | | - fcsr = c->fpu_csr31; |
---|
82 | | - mask = FPU_CSR_ALL_X | FPU_CSR_ALL_E | FPU_CSR_ALL_S | FPU_CSR_RM; |
---|
83 | | - |
---|
84 | | - sr = read_c0_status(); |
---|
85 | | - __enable_fpu(FPU_AS_IS); |
---|
86 | | - |
---|
87 | | - fcsr0 = fcsr & mask; |
---|
88 | | - write_32bit_cp1_register(CP1_STATUS, fcsr0); |
---|
89 | | - fcsr0 = read_32bit_cp1_register(CP1_STATUS); |
---|
90 | | - |
---|
91 | | - fcsr1 = fcsr | ~mask; |
---|
92 | | - write_32bit_cp1_register(CP1_STATUS, fcsr1); |
---|
93 | | - fcsr1 = read_32bit_cp1_register(CP1_STATUS); |
---|
94 | | - |
---|
95 | | - write_32bit_cp1_register(CP1_STATUS, fcsr); |
---|
96 | | - |
---|
97 | | - write_c0_status(sr); |
---|
98 | | - |
---|
99 | | - c->fpu_msk31 = ~(fcsr0 ^ fcsr1) & ~mask; |
---|
100 | | -} |
---|
101 | | - |
---|
102 | | -/* |
---|
103 | | - * Determine the IEEE 754 NaN encodings and ABS.fmt/NEG.fmt execution modes |
---|
104 | | - * supported by FPU hardware. |
---|
105 | | - */ |
---|
106 | | -static void cpu_set_fpu_2008(struct cpuinfo_mips *c) |
---|
107 | | -{ |
---|
108 | | - if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M64R1 | |
---|
109 | | - MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 | |
---|
110 | | - MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6)) { |
---|
111 | | - unsigned long sr, fir, fcsr, fcsr0, fcsr1; |
---|
112 | | - |
---|
113 | | - sr = read_c0_status(); |
---|
114 | | - __enable_fpu(FPU_AS_IS); |
---|
115 | | - |
---|
116 | | - fir = read_32bit_cp1_register(CP1_REVISION); |
---|
117 | | - if (fir & MIPS_FPIR_HAS2008) { |
---|
118 | | - fcsr = read_32bit_cp1_register(CP1_STATUS); |
---|
119 | | - |
---|
120 | | - fcsr0 = fcsr & ~(FPU_CSR_ABS2008 | FPU_CSR_NAN2008); |
---|
121 | | - write_32bit_cp1_register(CP1_STATUS, fcsr0); |
---|
122 | | - fcsr0 = read_32bit_cp1_register(CP1_STATUS); |
---|
123 | | - |
---|
124 | | - fcsr1 = fcsr | FPU_CSR_ABS2008 | FPU_CSR_NAN2008; |
---|
125 | | - write_32bit_cp1_register(CP1_STATUS, fcsr1); |
---|
126 | | - fcsr1 = read_32bit_cp1_register(CP1_STATUS); |
---|
127 | | - |
---|
128 | | - write_32bit_cp1_register(CP1_STATUS, fcsr); |
---|
129 | | - |
---|
130 | | - if (!(fcsr0 & FPU_CSR_NAN2008)) |
---|
131 | | - c->options |= MIPS_CPU_NAN_LEGACY; |
---|
132 | | - if (fcsr1 & FPU_CSR_NAN2008) |
---|
133 | | - c->options |= MIPS_CPU_NAN_2008; |
---|
134 | | - |
---|
135 | | - if ((fcsr0 ^ fcsr1) & FPU_CSR_ABS2008) |
---|
136 | | - c->fpu_msk31 &= ~FPU_CSR_ABS2008; |
---|
137 | | - else |
---|
138 | | - c->fpu_csr31 |= fcsr & FPU_CSR_ABS2008; |
---|
139 | | - |
---|
140 | | - if ((fcsr0 ^ fcsr1) & FPU_CSR_NAN2008) |
---|
141 | | - c->fpu_msk31 &= ~FPU_CSR_NAN2008; |
---|
142 | | - else |
---|
143 | | - c->fpu_csr31 |= fcsr & FPU_CSR_NAN2008; |
---|
144 | | - } else { |
---|
145 | | - c->options |= MIPS_CPU_NAN_LEGACY; |
---|
146 | | - } |
---|
147 | | - |
---|
148 | | - write_c0_status(sr); |
---|
149 | | - } else { |
---|
150 | | - c->options |= MIPS_CPU_NAN_LEGACY; |
---|
151 | | - } |
---|
152 | | -} |
---|
153 | | - |
---|
154 | | -/* |
---|
155 | | - * IEEE 754 conformance mode to use. Affects the NaN encoding and the |
---|
156 | | - * ABS.fmt/NEG.fmt execution mode. |
---|
157 | | - */ |
---|
158 | | -static enum { STRICT, LEGACY, STD2008, RELAXED } ieee754 = STRICT; |
---|
159 | | - |
---|
160 | | -/* |
---|
161 | | - * Set the IEEE 754 NaN encodings and the ABS.fmt/NEG.fmt execution modes |
---|
162 | | - * to support by the FPU emulator according to the IEEE 754 conformance |
---|
163 | | - * mode selected. Note that "relaxed" straps the emulator so that it |
---|
164 | | - * allows 2008-NaN binaries even for legacy processors. |
---|
165 | | - */ |
---|
166 | | -static void cpu_set_nofpu_2008(struct cpuinfo_mips *c) |
---|
167 | | -{ |
---|
168 | | - c->options &= ~(MIPS_CPU_NAN_2008 | MIPS_CPU_NAN_LEGACY); |
---|
169 | | - c->fpu_csr31 &= ~(FPU_CSR_ABS2008 | FPU_CSR_NAN2008); |
---|
170 | | - c->fpu_msk31 &= ~(FPU_CSR_ABS2008 | FPU_CSR_NAN2008); |
---|
171 | | - |
---|
172 | | - switch (ieee754) { |
---|
173 | | - case STRICT: |
---|
174 | | - if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M64R1 | |
---|
175 | | - MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 | |
---|
176 | | - MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6)) { |
---|
177 | | - c->options |= MIPS_CPU_NAN_2008 | MIPS_CPU_NAN_LEGACY; |
---|
178 | | - } else { |
---|
179 | | - c->options |= MIPS_CPU_NAN_LEGACY; |
---|
180 | | - c->fpu_msk31 |= FPU_CSR_ABS2008 | FPU_CSR_NAN2008; |
---|
181 | | - } |
---|
182 | | - break; |
---|
183 | | - case LEGACY: |
---|
184 | | - c->options |= MIPS_CPU_NAN_LEGACY; |
---|
185 | | - c->fpu_msk31 |= FPU_CSR_ABS2008 | FPU_CSR_NAN2008; |
---|
186 | | - break; |
---|
187 | | - case STD2008: |
---|
188 | | - c->options |= MIPS_CPU_NAN_2008; |
---|
189 | | - c->fpu_csr31 |= FPU_CSR_ABS2008 | FPU_CSR_NAN2008; |
---|
190 | | - c->fpu_msk31 |= FPU_CSR_ABS2008 | FPU_CSR_NAN2008; |
---|
191 | | - break; |
---|
192 | | - case RELAXED: |
---|
193 | | - c->options |= MIPS_CPU_NAN_2008 | MIPS_CPU_NAN_LEGACY; |
---|
194 | | - break; |
---|
195 | | - } |
---|
196 | | -} |
---|
197 | | - |
---|
198 | | -/* |
---|
199 | | - * Override the IEEE 754 NaN encoding and ABS.fmt/NEG.fmt execution mode |
---|
200 | | - * according to the "ieee754=" parameter. |
---|
201 | | - */ |
---|
202 | | -static void cpu_set_nan_2008(struct cpuinfo_mips *c) |
---|
203 | | -{ |
---|
204 | | - switch (ieee754) { |
---|
205 | | - case STRICT: |
---|
206 | | - mips_use_nan_legacy = !!cpu_has_nan_legacy; |
---|
207 | | - mips_use_nan_2008 = !!cpu_has_nan_2008; |
---|
208 | | - break; |
---|
209 | | - case LEGACY: |
---|
210 | | - mips_use_nan_legacy = !!cpu_has_nan_legacy; |
---|
211 | | - mips_use_nan_2008 = !cpu_has_nan_legacy; |
---|
212 | | - break; |
---|
213 | | - case STD2008: |
---|
214 | | - mips_use_nan_legacy = !cpu_has_nan_2008; |
---|
215 | | - mips_use_nan_2008 = !!cpu_has_nan_2008; |
---|
216 | | - break; |
---|
217 | | - case RELAXED: |
---|
218 | | - mips_use_nan_legacy = true; |
---|
219 | | - mips_use_nan_2008 = true; |
---|
220 | | - break; |
---|
221 | | - } |
---|
222 | | -} |
---|
223 | | - |
---|
224 | | -/* |
---|
225 | | - * IEEE 754 NaN encoding and ABS.fmt/NEG.fmt execution mode override |
---|
226 | | - * settings: |
---|
227 | | - * |
---|
228 | | - * strict: accept binaries that request a NaN encoding supported by the FPU |
---|
229 | | - * legacy: only accept legacy-NaN binaries |
---|
230 | | - * 2008: only accept 2008-NaN binaries |
---|
231 | | - * relaxed: accept any binaries regardless of whether supported by the FPU |
---|
232 | | - */ |
---|
233 | | -static int __init ieee754_setup(char *s) |
---|
234 | | -{ |
---|
235 | | - if (!s) |
---|
236 | | - return -1; |
---|
237 | | - else if (!strcmp(s, "strict")) |
---|
238 | | - ieee754 = STRICT; |
---|
239 | | - else if (!strcmp(s, "legacy")) |
---|
240 | | - ieee754 = LEGACY; |
---|
241 | | - else if (!strcmp(s, "2008")) |
---|
242 | | - ieee754 = STD2008; |
---|
243 | | - else if (!strcmp(s, "relaxed")) |
---|
244 | | - ieee754 = RELAXED; |
---|
245 | | - else |
---|
246 | | - return -1; |
---|
247 | | - |
---|
248 | | - if (!(boot_cpu_data.options & MIPS_CPU_FPU)) |
---|
249 | | - cpu_set_nofpu_2008(&boot_cpu_data); |
---|
250 | | - cpu_set_nan_2008(&boot_cpu_data); |
---|
251 | | - |
---|
252 | | - return 0; |
---|
253 | | -} |
---|
254 | | - |
---|
255 | | -early_param("ieee754", ieee754_setup); |
---|
256 | | - |
---|
257 | | -/* |
---|
258 | | - * Set the FIR feature flags for the FPU emulator. |
---|
259 | | - */ |
---|
260 | | -static void cpu_set_nofpu_id(struct cpuinfo_mips *c) |
---|
261 | | -{ |
---|
262 | | - u32 value; |
---|
263 | | - |
---|
264 | | - value = 0; |
---|
265 | | - if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M64R1 | |
---|
266 | | - MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 | |
---|
267 | | - MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6)) |
---|
268 | | - value |= MIPS_FPIR_D | MIPS_FPIR_S; |
---|
269 | | - if (c->isa_level & (MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 | |
---|
270 | | - MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6)) |
---|
271 | | - value |= MIPS_FPIR_F64 | MIPS_FPIR_L | MIPS_FPIR_W; |
---|
272 | | - if (c->options & MIPS_CPU_NAN_2008) |
---|
273 | | - value |= MIPS_FPIR_HAS2008; |
---|
274 | | - c->fpu_id = value; |
---|
275 | | -} |
---|
276 | | - |
---|
277 | | -/* Determined FPU emulator mask to use for the boot CPU with "nofpu". */ |
---|
278 | | -static unsigned int mips_nofpu_msk31; |
---|
279 | | - |
---|
280 | | -/* |
---|
281 | | - * Set options for FPU hardware. |
---|
282 | | - */ |
---|
283 | | -static void cpu_set_fpu_opts(struct cpuinfo_mips *c) |
---|
284 | | -{ |
---|
285 | | - c->fpu_id = cpu_get_fpu_id(); |
---|
286 | | - mips_nofpu_msk31 = c->fpu_msk31; |
---|
287 | | - |
---|
288 | | - if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M64R1 | |
---|
289 | | - MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 | |
---|
290 | | - MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6)) { |
---|
291 | | - if (c->fpu_id & MIPS_FPIR_3D) |
---|
292 | | - c->ases |= MIPS_ASE_MIPS3D; |
---|
293 | | - if (c->fpu_id & MIPS_FPIR_UFRP) |
---|
294 | | - c->options |= MIPS_CPU_UFR; |
---|
295 | | - if (c->fpu_id & MIPS_FPIR_FREP) |
---|
296 | | - c->options |= MIPS_CPU_FRE; |
---|
297 | | - } |
---|
298 | | - |
---|
299 | | - cpu_set_fpu_fcsr_mask(c); |
---|
300 | | - cpu_set_fpu_2008(c); |
---|
301 | | - cpu_set_nan_2008(c); |
---|
302 | | -} |
---|
303 | | - |
---|
304 | | -/* |
---|
305 | | - * Set options for the FPU emulator. |
---|
306 | | - */ |
---|
307 | | -static void cpu_set_nofpu_opts(struct cpuinfo_mips *c) |
---|
308 | | -{ |
---|
309 | | - c->options &= ~MIPS_CPU_FPU; |
---|
310 | | - c->fpu_msk31 = mips_nofpu_msk31; |
---|
311 | | - |
---|
312 | | - cpu_set_nofpu_2008(c); |
---|
313 | | - cpu_set_nan_2008(c); |
---|
314 | | - cpu_set_nofpu_id(c); |
---|
315 | | -} |
---|
316 | | - |
---|
317 | | -static int mips_fpu_disabled; |
---|
318 | | - |
---|
319 | | -static int __init fpu_disable(char *s) |
---|
320 | | -{ |
---|
321 | | - cpu_set_nofpu_opts(&boot_cpu_data); |
---|
322 | | - mips_fpu_disabled = 1; |
---|
323 | | - |
---|
324 | | - return 1; |
---|
325 | | -} |
---|
326 | | - |
---|
327 | | -__setup("nofpu", fpu_disable); |
---|
328 | 51 | |
---|
329 | 52 | static int mips_dsp_disabled; |
---|
330 | 53 | |
---|
.. | .. |
---|
475 | 198 | __elf_platform = plat; |
---|
476 | 199 | } |
---|
477 | 200 | |
---|
| 201 | +static inline void set_elf_base_platform(const char *plat) |
---|
| 202 | +{ |
---|
| 203 | + if (__elf_base_platform == NULL) { |
---|
| 204 | + __elf_base_platform = plat; |
---|
| 205 | + } |
---|
| 206 | +} |
---|
| 207 | + |
---|
478 | 208 | static inline void cpu_probe_vmbits(struct cpuinfo_mips *c) |
---|
479 | 209 | { |
---|
480 | 210 | #ifdef __NEED_VMBITS_PROBE |
---|
.. | .. |
---|
487 | 217 | static void set_isa(struct cpuinfo_mips *c, unsigned int isa) |
---|
488 | 218 | { |
---|
489 | 219 | switch (isa) { |
---|
| 220 | + case MIPS_CPU_ISA_M64R5: |
---|
| 221 | + c->isa_level |= MIPS_CPU_ISA_M32R5 | MIPS_CPU_ISA_M64R5; |
---|
| 222 | + set_elf_base_platform("mips64r5"); |
---|
| 223 | + fallthrough; |
---|
490 | 224 | case MIPS_CPU_ISA_M64R2: |
---|
491 | 225 | c->isa_level |= MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2; |
---|
| 226 | + set_elf_base_platform("mips64r2"); |
---|
| 227 | + fallthrough; |
---|
492 | 228 | case MIPS_CPU_ISA_M64R1: |
---|
493 | 229 | c->isa_level |= MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M64R1; |
---|
| 230 | + set_elf_base_platform("mips64"); |
---|
| 231 | + fallthrough; |
---|
494 | 232 | case MIPS_CPU_ISA_V: |
---|
495 | 233 | c->isa_level |= MIPS_CPU_ISA_V; |
---|
| 234 | + set_elf_base_platform("mips5"); |
---|
| 235 | + fallthrough; |
---|
496 | 236 | case MIPS_CPU_ISA_IV: |
---|
497 | 237 | c->isa_level |= MIPS_CPU_ISA_IV; |
---|
| 238 | + set_elf_base_platform("mips4"); |
---|
| 239 | + fallthrough; |
---|
498 | 240 | case MIPS_CPU_ISA_III: |
---|
499 | 241 | c->isa_level |= MIPS_CPU_ISA_II | MIPS_CPU_ISA_III; |
---|
| 242 | + set_elf_base_platform("mips3"); |
---|
500 | 243 | break; |
---|
501 | 244 | |
---|
502 | 245 | /* R6 incompatible with everything else */ |
---|
503 | 246 | case MIPS_CPU_ISA_M64R6: |
---|
504 | 247 | c->isa_level |= MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6; |
---|
| 248 | + set_elf_base_platform("mips64r6"); |
---|
| 249 | + fallthrough; |
---|
505 | 250 | case MIPS_CPU_ISA_M32R6: |
---|
506 | 251 | c->isa_level |= MIPS_CPU_ISA_M32R6; |
---|
| 252 | + set_elf_base_platform("mips32r6"); |
---|
507 | 253 | /* Break here so we don't add incompatible ISAs */ |
---|
508 | 254 | break; |
---|
| 255 | + case MIPS_CPU_ISA_M32R5: |
---|
| 256 | + c->isa_level |= MIPS_CPU_ISA_M32R5; |
---|
| 257 | + set_elf_base_platform("mips32r5"); |
---|
| 258 | + fallthrough; |
---|
509 | 259 | case MIPS_CPU_ISA_M32R2: |
---|
510 | 260 | c->isa_level |= MIPS_CPU_ISA_M32R2; |
---|
| 261 | + set_elf_base_platform("mips32r2"); |
---|
| 262 | + fallthrough; |
---|
511 | 263 | case MIPS_CPU_ISA_M32R1: |
---|
512 | 264 | c->isa_level |= MIPS_CPU_ISA_M32R1; |
---|
| 265 | + set_elf_base_platform("mips32"); |
---|
| 266 | + fallthrough; |
---|
513 | 267 | case MIPS_CPU_ISA_II: |
---|
514 | 268 | c->isa_level |= MIPS_CPU_ISA_II; |
---|
| 269 | + set_elf_base_platform("mips2"); |
---|
515 | 270 | break; |
---|
516 | 271 | } |
---|
517 | 272 | } |
---|
.. | .. |
---|
558 | 313 | config = read_c0_config6(); |
---|
559 | 314 | |
---|
560 | 315 | if (flags & FTLB_EN) |
---|
561 | | - config |= MIPS_CONF6_FTLBEN; |
---|
| 316 | + config |= MTI_CONF6_FTLBEN; |
---|
562 | 317 | else |
---|
563 | | - config &= ~MIPS_CONF6_FTLBEN; |
---|
| 318 | + config &= ~MTI_CONF6_FTLBEN; |
---|
564 | 319 | |
---|
565 | 320 | if (flags & FTLB_SET_PROB) { |
---|
566 | | - config &= ~(3 << MIPS_CONF6_FTLBP_SHIFT); |
---|
| 321 | + config &= ~(3 << MTI_CONF6_FTLBP_SHIFT); |
---|
567 | 322 | config |= calculate_ftlb_probability(c) |
---|
568 | | - << MIPS_CONF6_FTLBP_SHIFT; |
---|
| 323 | + << MTI_CONF6_FTLBP_SHIFT; |
---|
569 | 324 | } |
---|
570 | 325 | |
---|
571 | 326 | write_c0_config6(config); |
---|
.. | .. |
---|
577 | 332 | if (!(flags & FTLB_EN)) |
---|
578 | 333 | return 1; |
---|
579 | 334 | return 0; |
---|
580 | | - case CPU_LOONGSON3: |
---|
| 335 | + case CPU_LOONGSON64: |
---|
581 | 336 | /* Flush ITLB, DTLB, VTLB and FTLB */ |
---|
582 | 337 | write_c0_diag(LOONGSON_DIAG_ITLB | LOONGSON_DIAG_DTLB | |
---|
583 | 338 | LOONGSON_DIAG_VTLB | LOONGSON_DIAG_FTLB); |
---|
.. | .. |
---|
585 | 340 | config = read_c0_config6(); |
---|
586 | 341 | if (flags & FTLB_EN) |
---|
587 | 342 | /* Enable FTLB */ |
---|
588 | | - write_c0_config6(config & ~MIPS_CONF6_FTLBDIS); |
---|
| 343 | + write_c0_config6(config & ~LOONGSON_CONF6_FTLBDIS); |
---|
589 | 344 | else |
---|
590 | 345 | /* Disable FTLB */ |
---|
591 | | - write_c0_config6(config | MIPS_CONF6_FTLBDIS); |
---|
| 346 | + write_c0_config6(config | LOONGSON_CONF6_FTLBDIS); |
---|
592 | 347 | break; |
---|
593 | 348 | default: |
---|
594 | 349 | return 1; |
---|
| 350 | + } |
---|
| 351 | + |
---|
| 352 | + return 0; |
---|
| 353 | +} |
---|
| 354 | + |
---|
| 355 | +static int mm_config(struct cpuinfo_mips *c) |
---|
| 356 | +{ |
---|
| 357 | + unsigned int config0, update, mm; |
---|
| 358 | + |
---|
| 359 | + config0 = read_c0_config(); |
---|
| 360 | + mm = config0 & MIPS_CONF_MM; |
---|
| 361 | + |
---|
| 362 | + /* |
---|
| 363 | + * It's implementation dependent what type of write-merge is supported |
---|
| 364 | + * and whether it can be enabled/disabled. If it is settable lets make |
---|
| 365 | + * the merging allowed by default. Some platforms might have |
---|
| 366 | + * write-through caching unsupported. In this case just ignore the |
---|
| 367 | + * CP0.Config.MM bit field value. |
---|
| 368 | + */ |
---|
| 369 | + switch (c->cputype) { |
---|
| 370 | + case CPU_24K: |
---|
| 371 | + case CPU_34K: |
---|
| 372 | + case CPU_74K: |
---|
| 373 | + case CPU_P5600: |
---|
| 374 | + case CPU_P6600: |
---|
| 375 | + c->options |= MIPS_CPU_MM_FULL; |
---|
| 376 | + update = MIPS_CONF_MM_FULL; |
---|
| 377 | + break; |
---|
| 378 | + case CPU_1004K: |
---|
| 379 | + case CPU_1074K: |
---|
| 380 | + case CPU_INTERAPTIV: |
---|
| 381 | + case CPU_PROAPTIV: |
---|
| 382 | + mm = 0; |
---|
| 383 | + fallthrough; |
---|
| 384 | + default: |
---|
| 385 | + update = 0; |
---|
| 386 | + break; |
---|
| 387 | + } |
---|
| 388 | + |
---|
| 389 | + if (update) { |
---|
| 390 | + config0 = (config0 & ~MIPS_CONF_MM) | update; |
---|
| 391 | + write_c0_config(config0); |
---|
| 392 | + } else if (mm == MIPS_CONF_MM_SYSAD) { |
---|
| 393 | + c->options |= MIPS_CPU_MM_SYSAD; |
---|
| 394 | + } else if (mm == MIPS_CONF_MM_FULL) { |
---|
| 395 | + c->options |= MIPS_CPU_MM_FULL; |
---|
595 | 396 | } |
---|
596 | 397 | |
---|
597 | 398 | return 0; |
---|
.. | .. |
---|
788 | 589 | MIPS_CONF4_VTLBSIZEEXT_SHIFT) * 0x40; |
---|
789 | 590 | c->tlbsize = c->tlbsizevtlb; |
---|
790 | 591 | ftlb_page = MIPS_CONF4_VFTLBPAGESIZE; |
---|
791 | | - /* fall through */ |
---|
| 592 | + fallthrough; |
---|
792 | 593 | case MIPS_CONF4_MMUEXTDEF_FTLBSIZEEXT: |
---|
793 | 594 | if (mips_ftlb_disabled) |
---|
794 | 595 | break; |
---|
.. | .. |
---|
837 | 638 | |
---|
838 | 639 | static inline unsigned int decode_config5(struct cpuinfo_mips *c) |
---|
839 | 640 | { |
---|
840 | | - unsigned int config5; |
---|
| 641 | + unsigned int config5, max_mmid_width; |
---|
| 642 | + unsigned long asid_mask; |
---|
841 | 643 | |
---|
842 | 644 | config5 = read_c0_config5(); |
---|
843 | 645 | config5 &= ~(MIPS_CONF5_UFR | MIPS_CONF5_UFE); |
---|
| 646 | + |
---|
| 647 | + if (cpu_has_mips_r6) { |
---|
| 648 | + if (!__builtin_constant_p(cpu_has_mmid) || cpu_has_mmid) |
---|
| 649 | + config5 |= MIPS_CONF5_MI; |
---|
| 650 | + else |
---|
| 651 | + config5 &= ~MIPS_CONF5_MI; |
---|
| 652 | + } |
---|
| 653 | + |
---|
844 | 654 | write_c0_config5(config5); |
---|
845 | 655 | |
---|
846 | 656 | if (config5 & MIPS_CONF5_EVA) |
---|
.. | .. |
---|
858 | 668 | |
---|
859 | 669 | if (config5 & MIPS_CONF5_CRCP) |
---|
860 | 670 | elf_hwcap |= HWCAP_MIPS_CRC32; |
---|
| 671 | + |
---|
| 672 | + if (cpu_has_mips_r6) { |
---|
| 673 | + /* Ensure the write to config5 above takes effect */ |
---|
| 674 | + back_to_back_c0_hazard(); |
---|
| 675 | + |
---|
| 676 | + /* Check whether we successfully enabled MMID support */ |
---|
| 677 | + config5 = read_c0_config5(); |
---|
| 678 | + if (config5 & MIPS_CONF5_MI) |
---|
| 679 | + c->options |= MIPS_CPU_MMID; |
---|
| 680 | + |
---|
| 681 | + /* |
---|
| 682 | + * Warn if we've hardcoded cpu_has_mmid to a value unsuitable |
---|
| 683 | + * for the CPU we're running on, or if CPUs in an SMP system |
---|
| 684 | + * have inconsistent MMID support. |
---|
| 685 | + */ |
---|
| 686 | + WARN_ON(!!cpu_has_mmid != !!(config5 & MIPS_CONF5_MI)); |
---|
| 687 | + |
---|
| 688 | + if (cpu_has_mmid) { |
---|
| 689 | + write_c0_memorymapid(~0ul); |
---|
| 690 | + back_to_back_c0_hazard(); |
---|
| 691 | + asid_mask = read_c0_memorymapid(); |
---|
| 692 | + |
---|
| 693 | + /* |
---|
| 694 | + * We maintain a bitmap to track MMID allocation, and |
---|
| 695 | + * need a sensible upper bound on the size of that |
---|
| 696 | + * bitmap. The initial CPU with MMID support (I6500) |
---|
| 697 | + * supports 16 bit MMIDs, which gives us an 8KiB |
---|
| 698 | + * bitmap. The architecture recommends that hardware |
---|
| 699 | + * support 32 bit MMIDs, which would give us a 512MiB |
---|
| 700 | + * bitmap - that's too big in most cases. |
---|
| 701 | + * |
---|
| 702 | + * Cap MMID width at 16 bits for now & we can revisit |
---|
| 703 | + * this if & when hardware supports anything wider. |
---|
| 704 | + */ |
---|
| 705 | + max_mmid_width = 16; |
---|
| 706 | + if (asid_mask > GENMASK(max_mmid_width - 1, 0)) { |
---|
| 707 | + pr_info("Capping MMID width at %d bits", |
---|
| 708 | + max_mmid_width); |
---|
| 709 | + asid_mask = GENMASK(max_mmid_width - 1, 0); |
---|
| 710 | + } |
---|
| 711 | + |
---|
| 712 | + set_cpu_asid_mask(c, asid_mask); |
---|
| 713 | + } |
---|
| 714 | + } |
---|
861 | 715 | |
---|
862 | 716 | return config5 & MIPS_CONF_M; |
---|
863 | 717 | } |
---|
.. | .. |
---|
1300 | 1154 | break; |
---|
1301 | 1155 | } |
---|
1302 | 1156 | break; |
---|
1303 | | - case PRID_IMP_R4300: |
---|
1304 | | - c->cputype = CPU_R4300; |
---|
1305 | | - __cpu_name[cpu] = "R4300"; |
---|
1306 | | - set_isa(c, MIPS_CPU_ISA_III); |
---|
1307 | | - c->fpu_msk31 |= FPU_CSR_CONDX; |
---|
1308 | | - c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | |
---|
1309 | | - MIPS_CPU_LLSC; |
---|
1310 | | - c->tlbsize = 32; |
---|
1311 | | - break; |
---|
1312 | 1157 | case PRID_IMP_R4600: |
---|
1313 | 1158 | c->cputype = CPU_R4600; |
---|
1314 | 1159 | __cpu_name[cpu] = "R4600"; |
---|
.. | .. |
---|
1384 | 1229 | MIPS_CPU_LLSC; |
---|
1385 | 1230 | c->tlbsize = 48; |
---|
1386 | 1231 | break; |
---|
1387 | | - case PRID_IMP_R5432: |
---|
1388 | | - c->cputype = CPU_R5432; |
---|
1389 | | - __cpu_name[cpu] = "R5432"; |
---|
1390 | | - set_isa(c, MIPS_CPU_ISA_IV); |
---|
1391 | | - c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | |
---|
1392 | | - MIPS_CPU_WATCH | MIPS_CPU_LLSC; |
---|
1393 | | - c->tlbsize = 48; |
---|
1394 | | - break; |
---|
1395 | 1232 | case PRID_IMP_R5500: |
---|
1396 | 1233 | c->cputype = CPU_R5500; |
---|
1397 | 1234 | __cpu_name[cpu] = "R5500"; |
---|
.. | .. |
---|
1424 | 1261 | */ |
---|
1425 | 1262 | c->tlbsize = (read_c0_info() & (1 << 29)) ? 64 : 48; |
---|
1426 | 1263 | break; |
---|
1427 | | - case PRID_IMP_R8000: |
---|
1428 | | - c->cputype = CPU_R8000; |
---|
1429 | | - __cpu_name[cpu] = "RM8000"; |
---|
1430 | | - set_isa(c, MIPS_CPU_ISA_IV); |
---|
1431 | | - c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX | |
---|
1432 | | - MIPS_CPU_FPU | MIPS_CPU_32FPR | |
---|
1433 | | - MIPS_CPU_LLSC; |
---|
1434 | | - c->tlbsize = 384; /* has weird TLB: 3-way x 128 */ |
---|
1435 | | - break; |
---|
1436 | 1264 | case PRID_IMP_R10000: |
---|
1437 | 1265 | c->cputype = CPU_R10000; |
---|
1438 | 1266 | __cpu_name[cpu] = "R10000"; |
---|
.. | .. |
---|
1450 | 1278 | c->options = MIPS_CPU_TLB | MIPS_CPU_4K_CACHE | MIPS_CPU_4KEX | |
---|
1451 | 1279 | MIPS_CPU_FPU | MIPS_CPU_32FPR | |
---|
1452 | 1280 | MIPS_CPU_COUNTER | MIPS_CPU_WATCH | |
---|
1453 | | - MIPS_CPU_LLSC | MIPS_CPU_BP_GHIST; |
---|
| 1281 | + MIPS_CPU_LLSC; |
---|
1454 | 1282 | c->tlbsize = 64; |
---|
| 1283 | + write_c0_r10k_diag(read_c0_r10k_diag() | R10K_DIAG_E_GHIST); |
---|
1455 | 1284 | break; |
---|
1456 | 1285 | case PRID_IMP_R14000: |
---|
1457 | 1286 | if (((c->processor_id >> 4) & 0x0f) > 2) { |
---|
.. | .. |
---|
1465 | 1294 | c->options = MIPS_CPU_TLB | MIPS_CPU_4K_CACHE | MIPS_CPU_4KEX | |
---|
1466 | 1295 | MIPS_CPU_FPU | MIPS_CPU_32FPR | |
---|
1467 | 1296 | MIPS_CPU_COUNTER | MIPS_CPU_WATCH | |
---|
1468 | | - MIPS_CPU_LLSC | MIPS_CPU_BP_GHIST; |
---|
| 1297 | + MIPS_CPU_LLSC; |
---|
1469 | 1298 | c->tlbsize = 64; |
---|
| 1299 | + write_c0_r10k_diag(read_c0_r10k_diag() | R10K_DIAG_E_GHIST); |
---|
1470 | 1300 | break; |
---|
1471 | | - case PRID_IMP_LOONGSON_64: /* Loongson-2/3 */ |
---|
| 1301 | + case PRID_IMP_LOONGSON_64C: /* Loongson-2/3 */ |
---|
1472 | 1302 | switch (c->processor_id & PRID_REV_MASK) { |
---|
1473 | 1303 | case PRID_REV_LOONGSON2E: |
---|
1474 | | - c->cputype = CPU_LOONGSON2; |
---|
| 1304 | + c->cputype = CPU_LOONGSON2EF; |
---|
1475 | 1305 | __cpu_name[cpu] = "ICT Loongson-2"; |
---|
1476 | 1306 | set_elf_platform(cpu, "loongson2e"); |
---|
1477 | 1307 | set_isa(c, MIPS_CPU_ISA_III); |
---|
1478 | 1308 | c->fpu_msk31 |= FPU_CSR_CONDX; |
---|
1479 | 1309 | break; |
---|
1480 | 1310 | case PRID_REV_LOONGSON2F: |
---|
1481 | | - c->cputype = CPU_LOONGSON2; |
---|
| 1311 | + c->cputype = CPU_LOONGSON2EF; |
---|
1482 | 1312 | __cpu_name[cpu] = "ICT Loongson-2"; |
---|
1483 | 1313 | set_elf_platform(cpu, "loongson2f"); |
---|
1484 | 1314 | set_isa(c, MIPS_CPU_ISA_III); |
---|
1485 | 1315 | c->fpu_msk31 |= FPU_CSR_CONDX; |
---|
1486 | 1316 | break; |
---|
1487 | 1317 | case PRID_REV_LOONGSON3A_R1: |
---|
1488 | | - c->cputype = CPU_LOONGSON3; |
---|
| 1318 | + c->cputype = CPU_LOONGSON64; |
---|
1489 | 1319 | __cpu_name[cpu] = "ICT Loongson-3"; |
---|
1490 | 1320 | set_elf_platform(cpu, "loongson3a"); |
---|
1491 | 1321 | set_isa(c, MIPS_CPU_ISA_M64R1); |
---|
.. | .. |
---|
1494 | 1324 | break; |
---|
1495 | 1325 | case PRID_REV_LOONGSON3B_R1: |
---|
1496 | 1326 | case PRID_REV_LOONGSON3B_R2: |
---|
1497 | | - c->cputype = CPU_LOONGSON3; |
---|
| 1327 | + c->cputype = CPU_LOONGSON64; |
---|
1498 | 1328 | __cpu_name[cpu] = "ICT Loongson-3"; |
---|
1499 | 1329 | set_elf_platform(cpu, "loongson3b"); |
---|
1500 | 1330 | set_isa(c, MIPS_CPU_ISA_M64R1); |
---|
.. | .. |
---|
1507 | 1337 | MIPS_CPU_FPU | MIPS_CPU_LLSC | |
---|
1508 | 1338 | MIPS_CPU_32FPR; |
---|
1509 | 1339 | c->tlbsize = 64; |
---|
| 1340 | + set_cpu_asid_mask(c, MIPS_ENTRYHI_ASID); |
---|
1510 | 1341 | c->writecombine = _CACHE_UNCACHED_ACCELERATED; |
---|
1511 | 1342 | break; |
---|
1512 | 1343 | case PRID_IMP_LOONGSON_32: /* Loongson-1 */ |
---|
1513 | 1344 | decode_configs(c); |
---|
1514 | 1345 | |
---|
1515 | | - c->cputype = CPU_LOONGSON1; |
---|
| 1346 | + c->cputype = CPU_LOONGSON32; |
---|
1516 | 1347 | |
---|
1517 | 1348 | switch (c->processor_id & PRID_REV_MASK) { |
---|
1518 | 1349 | case PRID_REV_LOONGSON1B: |
---|
.. | .. |
---|
1660 | 1491 | |
---|
1661 | 1492 | spram_config(); |
---|
1662 | 1493 | |
---|
| 1494 | + mm_config(c); |
---|
| 1495 | + |
---|
1663 | 1496 | switch (__get_cpu_type(c->cputype)) { |
---|
| 1497 | + case CPU_M5150: |
---|
| 1498 | + case CPU_P5600: |
---|
| 1499 | + set_isa(c, MIPS_CPU_ISA_M32R5); |
---|
| 1500 | + break; |
---|
1664 | 1501 | case CPU_I6500: |
---|
1665 | 1502 | c->options |= MIPS_CPU_SHARED_FTLB_ENTRIES; |
---|
1666 | | - /* fall-through */ |
---|
| 1503 | + fallthrough; |
---|
1667 | 1504 | case CPU_I6400: |
---|
1668 | 1505 | c->options |= MIPS_CPU_SHARED_FTLB_RAM; |
---|
1669 | | - /* fall-through */ |
---|
| 1506 | + fallthrough; |
---|
1670 | 1507 | default: |
---|
| 1508 | + break; |
---|
| 1509 | + } |
---|
| 1510 | + |
---|
| 1511 | + /* Recent MIPS cores use the implementation-dependent ExcCode 16 for |
---|
| 1512 | + * cache/FTLB parity exceptions. |
---|
| 1513 | + */ |
---|
| 1514 | + switch (__get_cpu_type(c->cputype)) { |
---|
| 1515 | + case CPU_PROAPTIV: |
---|
| 1516 | + case CPU_P5600: |
---|
| 1517 | + case CPU_P6600: |
---|
| 1518 | + case CPU_I6400: |
---|
| 1519 | + case CPU_I6500: |
---|
| 1520 | + c->options |= MIPS_CPU_FTLBPAREX; |
---|
1671 | 1521 | break; |
---|
1672 | 1522 | } |
---|
1673 | 1523 | } |
---|
.. | .. |
---|
1842 | 1692 | } |
---|
1843 | 1693 | } |
---|
1844 | 1694 | |
---|
| 1695 | +#ifdef CONFIG_CPU_LOONGSON64 |
---|
| 1696 | +#include <loongson_regs.h> |
---|
| 1697 | + |
---|
| 1698 | +static inline void decode_cpucfg(struct cpuinfo_mips *c) |
---|
| 1699 | +{ |
---|
| 1700 | + u32 cfg1 = read_cpucfg(LOONGSON_CFG1); |
---|
| 1701 | + u32 cfg2 = read_cpucfg(LOONGSON_CFG2); |
---|
| 1702 | + u32 cfg3 = read_cpucfg(LOONGSON_CFG3); |
---|
| 1703 | + |
---|
| 1704 | + if (cfg1 & LOONGSON_CFG1_MMI) |
---|
| 1705 | + c->ases |= MIPS_ASE_LOONGSON_MMI; |
---|
| 1706 | + |
---|
| 1707 | + if (cfg2 & LOONGSON_CFG2_LEXT1) |
---|
| 1708 | + c->ases |= MIPS_ASE_LOONGSON_EXT; |
---|
| 1709 | + |
---|
| 1710 | + if (cfg2 & LOONGSON_CFG2_LEXT2) |
---|
| 1711 | + c->ases |= MIPS_ASE_LOONGSON_EXT2; |
---|
| 1712 | + |
---|
| 1713 | + if (cfg2 & LOONGSON_CFG2_LSPW) { |
---|
| 1714 | + c->options |= MIPS_CPU_LDPTE; |
---|
| 1715 | + c->guest.options |= MIPS_CPU_LDPTE; |
---|
| 1716 | + } |
---|
| 1717 | + |
---|
| 1718 | + if (cfg3 & LOONGSON_CFG3_LCAMP) |
---|
| 1719 | + c->ases |= MIPS_ASE_LOONGSON_CAM; |
---|
| 1720 | +} |
---|
| 1721 | + |
---|
1845 | 1722 | static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu) |
---|
1846 | 1723 | { |
---|
| 1724 | + c->cputype = CPU_LOONGSON64; |
---|
| 1725 | + |
---|
| 1726 | + /* All Loongson processors covered here define ExcCode 16 as GSExc. */ |
---|
| 1727 | + decode_configs(c); |
---|
| 1728 | + c->options |= MIPS_CPU_GSEXCEX; |
---|
| 1729 | + |
---|
1847 | 1730 | switch (c->processor_id & PRID_IMP_MASK) { |
---|
1848 | | - case PRID_IMP_LOONGSON_64: /* Loongson-2/3 */ |
---|
| 1731 | + case PRID_IMP_LOONGSON_64R: /* Loongson-64 Reduced */ |
---|
1849 | 1732 | switch (c->processor_id & PRID_REV_MASK) { |
---|
1850 | | - case PRID_REV_LOONGSON3A_R2: |
---|
1851 | | - c->cputype = CPU_LOONGSON3; |
---|
| 1733 | + case PRID_REV_LOONGSON2K_R1_0: |
---|
| 1734 | + case PRID_REV_LOONGSON2K_R1_1: |
---|
| 1735 | + case PRID_REV_LOONGSON2K_R1_2: |
---|
| 1736 | + case PRID_REV_LOONGSON2K_R1_3: |
---|
| 1737 | + __cpu_name[cpu] = "Loongson-2K"; |
---|
| 1738 | + set_elf_platform(cpu, "gs264e"); |
---|
| 1739 | + set_isa(c, MIPS_CPU_ISA_M64R2); |
---|
| 1740 | + break; |
---|
| 1741 | + } |
---|
| 1742 | + c->ases |= (MIPS_ASE_LOONGSON_MMI | MIPS_ASE_LOONGSON_EXT | |
---|
| 1743 | + MIPS_ASE_LOONGSON_EXT2); |
---|
| 1744 | + break; |
---|
| 1745 | + case PRID_IMP_LOONGSON_64C: /* Loongson-3 Classic */ |
---|
| 1746 | + switch (c->processor_id & PRID_REV_MASK) { |
---|
| 1747 | + case PRID_REV_LOONGSON3A_R2_0: |
---|
| 1748 | + case PRID_REV_LOONGSON3A_R2_1: |
---|
1852 | 1749 | __cpu_name[cpu] = "ICT Loongson-3"; |
---|
1853 | 1750 | set_elf_platform(cpu, "loongson3a"); |
---|
1854 | 1751 | set_isa(c, MIPS_CPU_ISA_M64R2); |
---|
1855 | 1752 | break; |
---|
1856 | 1753 | case PRID_REV_LOONGSON3A_R3_0: |
---|
1857 | 1754 | case PRID_REV_LOONGSON3A_R3_1: |
---|
1858 | | - c->cputype = CPU_LOONGSON3; |
---|
1859 | 1755 | __cpu_name[cpu] = "ICT Loongson-3"; |
---|
1860 | 1756 | set_elf_platform(cpu, "loongson3a"); |
---|
1861 | 1757 | set_isa(c, MIPS_CPU_ISA_M64R2); |
---|
1862 | 1758 | break; |
---|
1863 | 1759 | } |
---|
1864 | | - |
---|
1865 | | - decode_configs(c); |
---|
| 1760 | + /* |
---|
| 1761 | + * Loongson-3 Classic did not implement MIPS standard TLBINV |
---|
| 1762 | + * but implemented TLBINVF and EHINV. As currently we're only |
---|
| 1763 | + * using these two features, enable MIPS_CPU_TLBINV as well. |
---|
| 1764 | + * |
---|
| 1765 | + * Also some early Loongson-3A2000 had wrong TLB type in Config |
---|
| 1766 | + * register, we correct it here. |
---|
| 1767 | + */ |
---|
1866 | 1768 | c->options |= MIPS_CPU_FTLB | MIPS_CPU_TLBINV | MIPS_CPU_LDPTE; |
---|
1867 | | - c->writecombine = _CACHE_UNCACHED_ACCELERATED; |
---|
1868 | 1769 | c->ases |= (MIPS_ASE_LOONGSON_MMI | MIPS_ASE_LOONGSON_CAM | |
---|
1869 | 1770 | MIPS_ASE_LOONGSON_EXT | MIPS_ASE_LOONGSON_EXT2); |
---|
| 1771 | + c->ases &= ~MIPS_ASE_VZ; /* VZ of Loongson-3A2000/3000 is incomplete */ |
---|
| 1772 | + break; |
---|
| 1773 | + case PRID_IMP_LOONGSON_64G: |
---|
| 1774 | + __cpu_name[cpu] = "ICT Loongson-3"; |
---|
| 1775 | + set_elf_platform(cpu, "loongson3a"); |
---|
| 1776 | + set_isa(c, MIPS_CPU_ISA_M64R2); |
---|
| 1777 | + decode_cpucfg(c); |
---|
1870 | 1778 | break; |
---|
1871 | 1779 | default: |
---|
1872 | 1780 | panic("Unknown Loongson Processor ID!"); |
---|
1873 | 1781 | break; |
---|
1874 | 1782 | } |
---|
1875 | 1783 | } |
---|
| 1784 | +#else |
---|
| 1785 | +static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu) { } |
---|
| 1786 | +#endif |
---|
1876 | 1787 | |
---|
1877 | 1788 | static inline void cpu_probe_ingenic(struct cpuinfo_mips *c, unsigned int cpu) |
---|
1878 | 1789 | { |
---|
1879 | 1790 | decode_configs(c); |
---|
1880 | | - /* JZRISC does not implement the CP0 counter. */ |
---|
| 1791 | + |
---|
| 1792 | + /* |
---|
| 1793 | + * XBurst misses a config2 register, so config3 decode was skipped in |
---|
| 1794 | + * decode_configs(). |
---|
| 1795 | + */ |
---|
| 1796 | + decode_config3(c); |
---|
| 1797 | + |
---|
| 1798 | + /* XBurst does not implement the CP0 counter. */ |
---|
1881 | 1799 | c->options &= ~MIPS_CPU_COUNTER; |
---|
1882 | | - BUG_ON(!__builtin_constant_p(cpu_has_counter) || cpu_has_counter); |
---|
| 1800 | + BUG_ON(__builtin_constant_p(cpu_has_counter) && cpu_has_counter); |
---|
| 1801 | + |
---|
| 1802 | + /* XBurst has virtually tagged icache */ |
---|
| 1803 | + c->icache.flags |= MIPS_CACHE_VTAG; |
---|
| 1804 | + |
---|
1883 | 1805 | switch (c->processor_id & PRID_IMP_MASK) { |
---|
1884 | | - case PRID_IMP_JZRISC: |
---|
1885 | | - c->cputype = CPU_JZRISC; |
---|
1886 | | - c->writecombine = _CACHE_UNCACHED_ACCELERATED; |
---|
1887 | | - __cpu_name[cpu] = "Ingenic JZRISC"; |
---|
| 1806 | + |
---|
| 1807 | + /* XBurst®1 with MXU1.0/MXU1.1 SIMD ISA */ |
---|
| 1808 | + case PRID_IMP_XBURST_REV1: |
---|
| 1809 | + |
---|
1888 | 1810 | /* |
---|
1889 | 1811 | * The XBurst core by default attempts to avoid branch target |
---|
1890 | 1812 | * buffer lookups by detecting & special casing loops. This |
---|
.. | .. |
---|
1892 | 1814 | * Set cp0 config7 bit 4 to disable this feature. |
---|
1893 | 1815 | */ |
---|
1894 | 1816 | set_c0_config7(MIPS_CONF7_BTB_LOOP_EN); |
---|
| 1817 | + |
---|
| 1818 | + switch (c->processor_id & PRID_COMP_MASK) { |
---|
| 1819 | + |
---|
| 1820 | + /* |
---|
| 1821 | + * The config0 register in the XBurst CPUs with a processor ID of |
---|
| 1822 | + * PRID_COMP_INGENIC_D0 report themselves as MIPS32r2 compatible, |
---|
| 1823 | + * but they don't actually support this ISA. |
---|
| 1824 | + */ |
---|
| 1825 | + case PRID_COMP_INGENIC_D0: |
---|
| 1826 | + c->isa_level &= ~MIPS_CPU_ISA_M32R2; |
---|
| 1827 | + |
---|
| 1828 | + /* FPU is not properly detected on JZ4760(B). */ |
---|
| 1829 | + if (c->processor_id == 0x2ed0024f) |
---|
| 1830 | + c->options |= MIPS_CPU_FPU; |
---|
| 1831 | + |
---|
| 1832 | + fallthrough; |
---|
| 1833 | + |
---|
| 1834 | + /* |
---|
| 1835 | + * The config0 register in the XBurst CPUs with a processor ID of |
---|
| 1836 | + * PRID_COMP_INGENIC_D0 or PRID_COMP_INGENIC_D1 has an abandoned |
---|
| 1837 | + * huge page tlb mode, this mode is not compatible with the MIPS |
---|
| 1838 | + * standard, it will cause tlbmiss and into an infinite loop |
---|
| 1839 | + * (line 21 in the tlb-funcs.S) when starting the init process. |
---|
| 1840 | + * After chip reset, the default is HPTLB mode, Write 0xa9000000 |
---|
| 1841 | + * to cp0 register 5 sel 4 to switch back to VTLB mode to prevent |
---|
| 1842 | + * getting stuck. |
---|
| 1843 | + */ |
---|
| 1844 | + case PRID_COMP_INGENIC_D1: |
---|
| 1845 | + write_c0_page_ctrl(XBURST_PAGECTRL_HPTLB_DIS); |
---|
| 1846 | + break; |
---|
| 1847 | + |
---|
| 1848 | + default: |
---|
| 1849 | + break; |
---|
| 1850 | + } |
---|
| 1851 | + fallthrough; |
---|
| 1852 | + |
---|
| 1853 | + /* XBurst®1 with MXU2.0 SIMD ISA */ |
---|
| 1854 | + case PRID_IMP_XBURST_REV2: |
---|
| 1855 | + /* Ingenic uses the WA bit to achieve write-combine memory writes */ |
---|
| 1856 | + c->writecombine = _CACHE_CACHABLE_WA; |
---|
| 1857 | + c->cputype = CPU_XBURST; |
---|
| 1858 | + __cpu_name[cpu] = "Ingenic XBurst"; |
---|
1895 | 1859 | break; |
---|
| 1860 | + |
---|
| 1861 | + /* XBurst®2 with MXU2.1 SIMD ISA */ |
---|
| 1862 | + case PRID_IMP_XBURST2: |
---|
| 1863 | + c->cputype = CPU_XBURST; |
---|
| 1864 | + __cpu_name[cpu] = "Ingenic XBurst II"; |
---|
| 1865 | + break; |
---|
| 1866 | + |
---|
1896 | 1867 | default: |
---|
1897 | 1868 | panic("Unknown Ingenic Processor ID!"); |
---|
1898 | 1869 | break; |
---|
.. | .. |
---|
1988 | 1959 | |
---|
1989 | 1960 | const char *__cpu_name[NR_CPUS]; |
---|
1990 | 1961 | const char *__elf_platform; |
---|
| 1962 | +const char *__elf_base_platform; |
---|
1991 | 1963 | |
---|
1992 | 1964 | void cpu_probe(void) |
---|
1993 | 1965 | { |
---|
.. | .. |
---|
2037 | 2009 | case PRID_COMP_LOONGSON: |
---|
2038 | 2010 | cpu_probe_loongson(c, cpu); |
---|
2039 | 2011 | break; |
---|
| 2012 | + case PRID_COMP_INGENIC_13: |
---|
2040 | 2013 | case PRID_COMP_INGENIC_D0: |
---|
2041 | 2014 | case PRID_COMP_INGENIC_D1: |
---|
2042 | 2015 | case PRID_COMP_INGENIC_E1: |
---|
.. | .. |
---|
2082 | 2055 | cpu_set_fpu_opts(c); |
---|
2083 | 2056 | else |
---|
2084 | 2057 | cpu_set_nofpu_opts(c); |
---|
2085 | | - |
---|
2086 | | - if (cpu_has_bp_ghist) |
---|
2087 | | - write_c0_r10k_diag(read_c0_r10k_diag() | |
---|
2088 | | - R10K_DIAG_E_GHIST); |
---|
2089 | 2058 | |
---|
2090 | 2059 | if (cpu_has_mips_r2_r6) { |
---|
2091 | 2060 | c->srsets = ((read_c0_srsctl() >> 26) & 0x0f) + 1; |
---|
.. | .. |
---|
2143 | 2112 | |
---|
2144 | 2113 | cpu_probe_vmbits(c); |
---|
2145 | 2114 | |
---|
| 2115 | + /* Synthesize CPUCFG data if running on Loongson processors; |
---|
| 2116 | + * no-op otherwise. |
---|
| 2117 | + * |
---|
| 2118 | + * This looks at previously probed features, so keep this at bottom. |
---|
| 2119 | + */ |
---|
| 2120 | + loongson3_cpucfg_synthesize_data(c); |
---|
| 2121 | + |
---|
2146 | 2122 | #ifdef CONFIG_64BIT |
---|
2147 | 2123 | if (cpu == 0) |
---|
2148 | 2124 | __ua_limit = ~((1ull << cpu_vmbits) - 1); |
---|