12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * Processor capabilities determination functions.
41da177e4SLinus Torvalds *
51da177e4SLinus Torvalds * Copyright (C) xxxx the Anonymous
6010b853bSRalf Baechle * Copyright (C) 1994 - 2006 Ralf Baechle
74194318cSRalf Baechle * Copyright (C) 2003, 2004 Maciej W. Rozycki
8113c62d9SSteven J. Hill * Copyright (C) 2001, 2004, 2011, 2012 MIPS Technologies, Inc.
91da177e4SLinus Torvalds */
101da177e4SLinus Torvalds #include <linux/init.h>
111da177e4SLinus Torvalds #include <linux/kernel.h>
121da177e4SLinus Torvalds #include <linux/ptrace.h>
13631330f5SRalf Baechle #include <linux/smp.h>
141da177e4SLinus Torvalds #include <linux/stddef.h>
1573bc256dSPaul Gortmaker #include <linux/export.h>
161da177e4SLinus Torvalds
175759906cSRalf Baechle #include <asm/bugs.h>
181da177e4SLinus Torvalds #include <asm/cpu.h>
19f6843626SMaciej W. Rozycki #include <asm/cpu-features.h>
2069f24d17SRalf Baechle #include <asm/cpu-type.h>
211da177e4SLinus Torvalds #include <asm/fpu.h>
221da177e4SLinus Torvalds #include <asm/mipsregs.h>
2330ee615bSPaul Burton #include <asm/mipsmtregs.h>
24a5e9a69eSPaul Burton #include <asm/msa.h>
25654f57bfSDavid Daney #include <asm/watch.h>
2606372a63SPaul Gortmaker #include <asm/elf.h>
274f12b91dSMarkos Chandras #include <asm/pgtable-bits.h>
28a074f0e8SChris Dearman #include <asm/spram.h>
29bd67b711SThomas Bogendoerfer #include <asm/traps.h>
307c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
31949e51beSDavid Daney
32a616c061SThomas Bogendoerfer #include "fpu-probe.h"
33a616c061SThomas Bogendoerfer
34ec7a9318SWANG Xuerui #include <asm/mach-loongson64/cpucfg-emul.h>
35ec7a9318SWANG Xuerui
36e14f1db7SPaul Burton /* Hardware capabilities */
37e14f1db7SPaul Burton unsigned int elf_hwcap __read_mostly;
3805510f2bSMarcin Nowakowski EXPORT_SYMBOL_GPL(elf_hwcap);
39e14f1db7SPaul Burton
cpu_get_msa_id(void)40b2e628a8SPaul Burton static inline unsigned long cpu_get_msa_id(void)
41b2e628a8SPaul Burton {
42b2e628a8SPaul Burton unsigned long status, msa_id;
43b2e628a8SPaul Burton
44b2e628a8SPaul Burton status = read_c0_status();
45b2e628a8SPaul Burton __enable_fpu(FPU_64BIT);
46b2e628a8SPaul Burton enable_msa();
47b2e628a8SPaul Burton msa_id = read_msa_ir();
48b2e628a8SPaul Burton disable_msa();
49b2e628a8SPaul Burton write_c0_status(status);
50b2e628a8SPaul Burton return msa_id;
51b2e628a8SPaul Burton }
52b2e628a8SPaul Burton
53b7fc2cc5SPaul Burton static int mips_dsp_disabled;
540103d23fSKevin Cernekee
dsp_disable(char * s)550103d23fSKevin Cernekee static int __init dsp_disable(char *s)
560103d23fSKevin Cernekee {
57ee80f7c7SSteven J. Hill cpu_data[0].ases &= ~(MIPS_ASE_DSP | MIPS_ASE_DSP2P);
580103d23fSKevin Cernekee mips_dsp_disabled = 1;
590103d23fSKevin Cernekee
600103d23fSKevin Cernekee return 1;
610103d23fSKevin Cernekee }
620103d23fSKevin Cernekee
630103d23fSKevin Cernekee __setup("nodsp", dsp_disable);
640103d23fSKevin Cernekee
653d528b32SMarkos Chandras static int mips_htw_disabled;
663d528b32SMarkos Chandras
htw_disable(char * s)673d528b32SMarkos Chandras static int __init htw_disable(char *s)
683d528b32SMarkos Chandras {
693d528b32SMarkos Chandras mips_htw_disabled = 1;
703d528b32SMarkos Chandras cpu_data[0].options &= ~MIPS_CPU_HTW;
713d528b32SMarkos Chandras write_c0_pwctl(read_c0_pwctl() &
723d528b32SMarkos Chandras ~(1 << MIPS_PWCTL_PWEN_SHIFT));
733d528b32SMarkos Chandras
743d528b32SMarkos Chandras return 1;
753d528b32SMarkos Chandras }
763d528b32SMarkos Chandras
773d528b32SMarkos Chandras __setup("nohtw", htw_disable);
783d528b32SMarkos Chandras
7997f4ad29SMarkos Chandras static int mips_ftlb_disabled;
8097f4ad29SMarkos Chandras static int mips_has_ftlb_configured;
8197f4ad29SMarkos Chandras
82ebd0e0f5SPaul Burton enum ftlb_flags {
83ebd0e0f5SPaul Burton FTLB_EN = 1 << 0,
84ebd0e0f5SPaul Burton FTLB_SET_PROB = 1 << 1,
85ebd0e0f5SPaul Burton };
86ebd0e0f5SPaul Burton
87ebd0e0f5SPaul Burton static int set_ftlb_enable(struct cpuinfo_mips *c, enum ftlb_flags flags);
8897f4ad29SMarkos Chandras
ftlb_disable(char * s)8997f4ad29SMarkos Chandras static int __init ftlb_disable(char *s)
9097f4ad29SMarkos Chandras {
9197f4ad29SMarkos Chandras unsigned int config4, mmuextdef;
9297f4ad29SMarkos Chandras
9397f4ad29SMarkos Chandras /*
9497f4ad29SMarkos Chandras * If the core hasn't done any FTLB configuration, there is nothing
9597f4ad29SMarkos Chandras * for us to do here.
9697f4ad29SMarkos Chandras */
9797f4ad29SMarkos Chandras if (!mips_has_ftlb_configured)
9897f4ad29SMarkos Chandras return 1;
9997f4ad29SMarkos Chandras
10097f4ad29SMarkos Chandras /* Disable it in the boot cpu */
101912708c2SMarkos Chandras if (set_ftlb_enable(&cpu_data[0], 0)) {
102912708c2SMarkos Chandras pr_warn("Can't turn FTLB off\n");
103912708c2SMarkos Chandras return 1;
104912708c2SMarkos Chandras }
10597f4ad29SMarkos Chandras
10697f4ad29SMarkos Chandras config4 = read_c0_config4();
10797f4ad29SMarkos Chandras
10897f4ad29SMarkos Chandras /* Check that FTLB has been disabled */
10997f4ad29SMarkos Chandras mmuextdef = config4 & MIPS_CONF4_MMUEXTDEF;
11097f4ad29SMarkos Chandras /* MMUSIZEEXT == VTLB ON, FTLB OFF */
11197f4ad29SMarkos Chandras if (mmuextdef == MIPS_CONF4_MMUEXTDEF_FTLBSIZEEXT) {
11297f4ad29SMarkos Chandras /* This should never happen */
11397f4ad29SMarkos Chandras pr_warn("FTLB could not be disabled!\n");
11497f4ad29SMarkos Chandras return 1;
11597f4ad29SMarkos Chandras }
11697f4ad29SMarkos Chandras
11797f4ad29SMarkos Chandras mips_ftlb_disabled = 1;
11897f4ad29SMarkos Chandras mips_has_ftlb_configured = 0;
11997f4ad29SMarkos Chandras
12097f4ad29SMarkos Chandras /*
12197f4ad29SMarkos Chandras * noftlb is mainly used for debug purposes so print
12297f4ad29SMarkos Chandras * an informative message instead of using pr_debug()
12397f4ad29SMarkos Chandras */
12497f4ad29SMarkos Chandras pr_info("FTLB has been disabled\n");
12597f4ad29SMarkos Chandras
12697f4ad29SMarkos Chandras /*
12797f4ad29SMarkos Chandras * Some of these bits are duplicated in the decode_config4.
12897f4ad29SMarkos Chandras * MIPS_CONF4_MMUEXTDEF_MMUSIZEEXT is the only possible case
12997f4ad29SMarkos Chandras * once FTLB has been disabled so undo what decode_config4 did.
13097f4ad29SMarkos Chandras */
13197f4ad29SMarkos Chandras cpu_data[0].tlbsize -= cpu_data[0].tlbsizeftlbways *
13297f4ad29SMarkos Chandras cpu_data[0].tlbsizeftlbsets;
13397f4ad29SMarkos Chandras cpu_data[0].tlbsizeftlbsets = 0;
13497f4ad29SMarkos Chandras cpu_data[0].tlbsizeftlbways = 0;
13597f4ad29SMarkos Chandras
13697f4ad29SMarkos Chandras return 1;
13797f4ad29SMarkos Chandras }
13897f4ad29SMarkos Chandras
13997f4ad29SMarkos Chandras __setup("noftlb", ftlb_disable);
14097f4ad29SMarkos Chandras
1418270ab48SMatt Redfearn /*
1428270ab48SMatt Redfearn * Check if the CPU has per tc perf counters
1438270ab48SMatt Redfearn */
cpu_set_mt_per_tc_perf(struct cpuinfo_mips * c)1448270ab48SMatt Redfearn static inline void cpu_set_mt_per_tc_perf(struct cpuinfo_mips *c)
1458270ab48SMatt Redfearn {
1468270ab48SMatt Redfearn if (read_c0_config7() & MTI_CONF7_PTC)
1478270ab48SMatt Redfearn c->options |= MIPS_CPU_MT_PER_TC_PERF_COUNTERS;
1488270ab48SMatt Redfearn }
14997f4ad29SMarkos Chandras
check_errata(void)1509267a30dSMarc St-Jean static inline void check_errata(void)
1519267a30dSMarc St-Jean {
1529267a30dSMarc St-Jean struct cpuinfo_mips *c = ¤t_cpu_data;
1539267a30dSMarc St-Jean
15469f24d17SRalf Baechle switch (current_cpu_type()) {
1559267a30dSMarc St-Jean case CPU_34K:
1569267a30dSMarc St-Jean /*
1579267a30dSMarc St-Jean * Erratum "RPS May Cause Incorrect Instruction Execution"
158b633648cSRalf Baechle * This code only handles VPE0, any SMP/RTOS code
15994bd83e4SJulia Lawall * making use of VPE1 will be responsible for that VPE.
1609267a30dSMarc St-Jean */
1619267a30dSMarc St-Jean if ((c->processor_id & PRID_REV_MASK) <= PRID_REV_34K_V1_0_2)
1629267a30dSMarc St-Jean write_c0_config7(read_c0_config7() | MIPS_CONF7_RPS);
1639267a30dSMarc St-Jean break;
1649267a30dSMarc St-Jean default:
1659267a30dSMarc St-Jean break;
1669267a30dSMarc St-Jean }
1679267a30dSMarc St-Jean }
1689267a30dSMarc St-Jean
check_bugs32(void)1691da177e4SLinus Torvalds void __init check_bugs32(void)
1701da177e4SLinus Torvalds {
1719267a30dSMarc St-Jean check_errata();
1721da177e4SLinus Torvalds }
1731da177e4SLinus Torvalds
1741da177e4SLinus Torvalds /*
1751da177e4SLinus Torvalds * Probe whether cpu has config register by trying to play with
1761da177e4SLinus Torvalds * alternate cache bit and see whether it matters.
1771da177e4SLinus Torvalds * It's used by cpu_probe to distinguish between R3000A and R3081.
1781da177e4SLinus Torvalds */
cpu_has_confreg(void)1791da177e4SLinus Torvalds static inline int cpu_has_confreg(void)
1801da177e4SLinus Torvalds {
1811da177e4SLinus Torvalds #ifdef CONFIG_CPU_R3000
1821da177e4SLinus Torvalds extern unsigned long r3k_cache_size(unsigned long);
1831da177e4SLinus Torvalds unsigned long size1, size2;
1841da177e4SLinus Torvalds unsigned long cfg = read_c0_conf();
1851da177e4SLinus Torvalds
1861da177e4SLinus Torvalds size1 = r3k_cache_size(ST0_ISC);
1871da177e4SLinus Torvalds write_c0_conf(cfg ^ R30XX_CONF_AC);
1881da177e4SLinus Torvalds size2 = r3k_cache_size(ST0_ISC);
1891da177e4SLinus Torvalds write_c0_conf(cfg);
1901da177e4SLinus Torvalds return size1 != size2;
1911da177e4SLinus Torvalds #else
1921da177e4SLinus Torvalds return 0;
1931da177e4SLinus Torvalds #endif
1941da177e4SLinus Torvalds }
1951da177e4SLinus Torvalds
set_elf_platform(int cpu,const char * plat)196c094c99eSRobert Millan static inline void set_elf_platform(int cpu, const char *plat)
197c094c99eSRobert Millan {
198c094c99eSRobert Millan if (cpu == 0)
199c094c99eSRobert Millan __elf_platform = plat;
200c094c99eSRobert Millan }
201c094c99eSRobert Millan
set_elf_base_platform(const char * plat)202e585b768SYunQiang Su static inline void set_elf_base_platform(const char *plat)
203e585b768SYunQiang Su {
204e585b768SYunQiang Su if (__elf_base_platform == NULL) {
205e585b768SYunQiang Su __elf_base_platform = plat;
206e585b768SYunQiang Su }
207e585b768SYunQiang Su }
208e585b768SYunQiang Su
cpu_probe_vmbits(struct cpuinfo_mips * c)20991dfc423SGuenter Roeck static inline void cpu_probe_vmbits(struct cpuinfo_mips *c)
21091dfc423SGuenter Roeck {
21191dfc423SGuenter Roeck #ifdef __NEED_VMBITS_PROBE
2125b7efa89SDavid Daney write_c0_entryhi(0x3fffffffffffe000ULL);
21391dfc423SGuenter Roeck back_to_back_c0_hazard();
2145b7efa89SDavid Daney c->vmbits = fls64(read_c0_entryhi() & 0x3fffffffffffe000ULL);
21591dfc423SGuenter Roeck #endif
21691dfc423SGuenter Roeck }
21791dfc423SGuenter Roeck
set_isa(struct cpuinfo_mips * c,unsigned int isa)218078a55fcSPaul Gortmaker static void set_isa(struct cpuinfo_mips *c, unsigned int isa)
219a96102beSSteven J. Hill {
220a96102beSSteven J. Hill switch (isa) {
221ab7c01fdSSerge Semin case MIPS_CPU_ISA_M64R5:
222ab7c01fdSSerge Semin c->isa_level |= MIPS_CPU_ISA_M32R5 | MIPS_CPU_ISA_M64R5;
223ab7c01fdSSerge Semin set_elf_base_platform("mips64r5");
224ab7c01fdSSerge Semin fallthrough;
225a96102beSSteven J. Hill case MIPS_CPU_ISA_M64R2:
226a96102beSSteven J. Hill c->isa_level |= MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2;
227e585b768SYunQiang Su set_elf_base_platform("mips64r2");
228c9b02990SLiangliang Huang fallthrough;
229a96102beSSteven J. Hill case MIPS_CPU_ISA_M64R1:
230a96102beSSteven J. Hill c->isa_level |= MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M64R1;
231e585b768SYunQiang Su set_elf_base_platform("mips64");
232c9b02990SLiangliang Huang fallthrough;
233a96102beSSteven J. Hill case MIPS_CPU_ISA_V:
234a96102beSSteven J. Hill c->isa_level |= MIPS_CPU_ISA_V;
235e585b768SYunQiang Su set_elf_base_platform("mips5");
236c9b02990SLiangliang Huang fallthrough;
237a96102beSSteven J. Hill case MIPS_CPU_ISA_IV:
238a96102beSSteven J. Hill c->isa_level |= MIPS_CPU_ISA_IV;
239e585b768SYunQiang Su set_elf_base_platform("mips4");
240c9b02990SLiangliang Huang fallthrough;
241a96102beSSteven J. Hill case MIPS_CPU_ISA_III:
2421990e542SRalf Baechle c->isa_level |= MIPS_CPU_ISA_II | MIPS_CPU_ISA_III;
243e585b768SYunQiang Su set_elf_base_platform("mips3");
244a96102beSSteven J. Hill break;
245a96102beSSteven J. Hill
2468b8aa636SLeonid Yegoshin /* R6 incompatible with everything else */
2478b8aa636SLeonid Yegoshin case MIPS_CPU_ISA_M64R6:
2488b8aa636SLeonid Yegoshin c->isa_level |= MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6;
249e585b768SYunQiang Su set_elf_base_platform("mips64r6");
250c9b02990SLiangliang Huang fallthrough;
2518b8aa636SLeonid Yegoshin case MIPS_CPU_ISA_M32R6:
2528b8aa636SLeonid Yegoshin c->isa_level |= MIPS_CPU_ISA_M32R6;
253e585b768SYunQiang Su set_elf_base_platform("mips32r6");
2548b8aa636SLeonid Yegoshin /* Break here so we don't add incompatible ISAs */
2558b8aa636SLeonid Yegoshin break;
256ab7c01fdSSerge Semin case MIPS_CPU_ISA_M32R5:
257ab7c01fdSSerge Semin c->isa_level |= MIPS_CPU_ISA_M32R5;
258ab7c01fdSSerge Semin set_elf_base_platform("mips32r5");
259ab7c01fdSSerge Semin fallthrough;
260a96102beSSteven J. Hill case MIPS_CPU_ISA_M32R2:
261a96102beSSteven J. Hill c->isa_level |= MIPS_CPU_ISA_M32R2;
262e585b768SYunQiang Su set_elf_base_platform("mips32r2");
263c9b02990SLiangliang Huang fallthrough;
264a96102beSSteven J. Hill case MIPS_CPU_ISA_M32R1:
265a96102beSSteven J. Hill c->isa_level |= MIPS_CPU_ISA_M32R1;
266e585b768SYunQiang Su set_elf_base_platform("mips32");
267c9b02990SLiangliang Huang fallthrough;
268a96102beSSteven J. Hill case MIPS_CPU_ISA_II:
269a96102beSSteven J. Hill c->isa_level |= MIPS_CPU_ISA_II;
270e585b768SYunQiang Su set_elf_base_platform("mips2");
271a96102beSSteven J. Hill break;
272a96102beSSteven J. Hill }
273a96102beSSteven J. Hill }
274a96102beSSteven J. Hill
275078a55fcSPaul Gortmaker static char unknown_isa[] = KERN_ERR \
2762fa36399SKelvin Cheung "Unsupported ISA type, c0.config0: %d.";
2772fa36399SKelvin Cheung
calculate_ftlb_probability(struct cpuinfo_mips * c)278cf0a8aa0SMarkos Chandras static unsigned int calculate_ftlb_probability(struct cpuinfo_mips *c)
279cf0a8aa0SMarkos Chandras {
280cf0a8aa0SMarkos Chandras
281cf0a8aa0SMarkos Chandras unsigned int probability = c->tlbsize / c->tlbsizevtlb;
282cf0a8aa0SMarkos Chandras
283cf0a8aa0SMarkos Chandras /*
284cf0a8aa0SMarkos Chandras * 0 = All TLBWR instructions go to FTLB
285cf0a8aa0SMarkos Chandras * 1 = 15:1: For every 16 TBLWR instructions, 15 go to the
286cf0a8aa0SMarkos Chandras * FTLB and 1 goes to the VTLB.
287cf0a8aa0SMarkos Chandras * 2 = 7:1: As above with 7:1 ratio.
288cf0a8aa0SMarkos Chandras * 3 = 3:1: As above with 3:1 ratio.
289cf0a8aa0SMarkos Chandras *
290cf0a8aa0SMarkos Chandras * Use the linear midpoint as the probability threshold.
291cf0a8aa0SMarkos Chandras */
292cf0a8aa0SMarkos Chandras if (probability >= 12)
293cf0a8aa0SMarkos Chandras return 1;
294cf0a8aa0SMarkos Chandras else if (probability >= 6)
295cf0a8aa0SMarkos Chandras return 2;
296cf0a8aa0SMarkos Chandras else
297cf0a8aa0SMarkos Chandras /*
298cf0a8aa0SMarkos Chandras * So FTLB is less than 4 times bigger than VTLB.
299cf0a8aa0SMarkos Chandras * A 3:1 ratio can still be useful though.
300cf0a8aa0SMarkos Chandras */
301cf0a8aa0SMarkos Chandras return 3;
302cf0a8aa0SMarkos Chandras }
303cf0a8aa0SMarkos Chandras
set_ftlb_enable(struct cpuinfo_mips * c,enum ftlb_flags flags)304ebd0e0f5SPaul Burton static int set_ftlb_enable(struct cpuinfo_mips *c, enum ftlb_flags flags)
30575b5b5e0SLeonid Yegoshin {
30620a7f7e5SMarkos Chandras unsigned int config;
307d83b0e82SJames Hogan
308d83b0e82SJames Hogan /* It's implementation dependent how the FTLB can be enabled */
309d83b0e82SJames Hogan switch (c->cputype) {
310d83b0e82SJames Hogan case CPU_PROAPTIV:
311d83b0e82SJames Hogan case CPU_P5600:
3121091bfa2SPaul Burton case CPU_P6600:
313d83b0e82SJames Hogan /* proAptiv & related cores use Config6 to enable the FTLB */
31420a7f7e5SMarkos Chandras config = read_c0_config6();
315ebd0e0f5SPaul Burton
316ebd0e0f5SPaul Burton if (flags & FTLB_EN)
31704ef32afSHuacai Chen config |= MTI_CONF6_FTLBEN;
31875b5b5e0SLeonid Yegoshin else
31904ef32afSHuacai Chen config &= ~MTI_CONF6_FTLBEN;
320ebd0e0f5SPaul Burton
321ebd0e0f5SPaul Burton if (flags & FTLB_SET_PROB) {
32204ef32afSHuacai Chen config &= ~(3 << MTI_CONF6_FTLBP_SHIFT);
323ebd0e0f5SPaul Burton config |= calculate_ftlb_probability(c)
32404ef32afSHuacai Chen << MTI_CONF6_FTLBP_SHIFT;
325ebd0e0f5SPaul Burton }
326ebd0e0f5SPaul Burton
327ebd0e0f5SPaul Burton write_c0_config6(config);
32867acd8d5SPaul Burton back_to_back_c0_hazard();
32920a7f7e5SMarkos Chandras break;
33020a7f7e5SMarkos Chandras case CPU_I6400:
331859aeb1bSPaul Burton case CPU_I6500:
33272c70f01SPaul Burton /* There's no way to disable the FTLB */
333ebd0e0f5SPaul Burton if (!(flags & FTLB_EN))
334ebd0e0f5SPaul Burton return 1;
335ebd0e0f5SPaul Burton return 0;
336268a2d60SJiaxun Yang case CPU_LOONGSON64:
33706e4814eSHuacai Chen /* Flush ITLB, DTLB, VTLB and FTLB */
33806e4814eSHuacai Chen write_c0_diag(LOONGSON_DIAG_ITLB | LOONGSON_DIAG_DTLB |
33906e4814eSHuacai Chen LOONGSON_DIAG_VTLB | LOONGSON_DIAG_FTLB);
340b2edcfc8SHuacai Chen /* Loongson-3 cores use Config6 to enable the FTLB */
341b2edcfc8SHuacai Chen config = read_c0_config6();
342ebd0e0f5SPaul Burton if (flags & FTLB_EN)
343b2edcfc8SHuacai Chen /* Enable FTLB */
34404ef32afSHuacai Chen write_c0_config6(config & ~LOONGSON_CONF6_FTLBDIS);
345b2edcfc8SHuacai Chen else
346b2edcfc8SHuacai Chen /* Disable FTLB */
34704ef32afSHuacai Chen write_c0_config6(config | LOONGSON_CONF6_FTLBDIS);
348b2edcfc8SHuacai Chen break;
349912708c2SMarkos Chandras default:
350912708c2SMarkos Chandras return 1;
35175b5b5e0SLeonid Yegoshin }
352912708c2SMarkos Chandras
353912708c2SMarkos Chandras return 0;
35475b5b5e0SLeonid Yegoshin }
35575b5b5e0SLeonid Yegoshin
mm_config(struct cpuinfo_mips * c)356742318adSSerge Semin static int mm_config(struct cpuinfo_mips *c)
357742318adSSerge Semin {
358742318adSSerge Semin unsigned int config0, update, mm;
359742318adSSerge Semin
360742318adSSerge Semin config0 = read_c0_config();
361742318adSSerge Semin mm = config0 & MIPS_CONF_MM;
362742318adSSerge Semin
363742318adSSerge Semin /*
364742318adSSerge Semin * It's implementation dependent what type of write-merge is supported
365742318adSSerge Semin * and whether it can be enabled/disabled. If it is settable lets make
366742318adSSerge Semin * the merging allowed by default. Some platforms might have
367742318adSSerge Semin * write-through caching unsupported. In this case just ignore the
368742318adSSerge Semin * CP0.Config.MM bit field value.
369742318adSSerge Semin */
370742318adSSerge Semin switch (c->cputype) {
371742318adSSerge Semin case CPU_24K:
372742318adSSerge Semin case CPU_34K:
373742318adSSerge Semin case CPU_74K:
374742318adSSerge Semin case CPU_P5600:
375742318adSSerge Semin case CPU_P6600:
376742318adSSerge Semin c->options |= MIPS_CPU_MM_FULL;
377742318adSSerge Semin update = MIPS_CONF_MM_FULL;
378742318adSSerge Semin break;
379742318adSSerge Semin case CPU_1004K:
380742318adSSerge Semin case CPU_1074K:
381742318adSSerge Semin case CPU_INTERAPTIV:
382742318adSSerge Semin case CPU_PROAPTIV:
383742318adSSerge Semin mm = 0;
384742318adSSerge Semin fallthrough;
385742318adSSerge Semin default:
386742318adSSerge Semin update = 0;
387742318adSSerge Semin break;
388742318adSSerge Semin }
389742318adSSerge Semin
390742318adSSerge Semin if (update) {
391742318adSSerge Semin config0 = (config0 & ~MIPS_CONF_MM) | update;
392742318adSSerge Semin write_c0_config(config0);
393742318adSSerge Semin } else if (mm == MIPS_CONF_MM_SYSAD) {
394742318adSSerge Semin c->options |= MIPS_CPU_MM_SYSAD;
395742318adSSerge Semin } else if (mm == MIPS_CONF_MM_FULL) {
396742318adSSerge Semin c->options |= MIPS_CPU_MM_FULL;
397742318adSSerge Semin }
398742318adSSerge Semin
399742318adSSerge Semin return 0;
400742318adSSerge Semin }
401742318adSSerge Semin
decode_config0(struct cpuinfo_mips * c)4022fa36399SKelvin Cheung static inline unsigned int decode_config0(struct cpuinfo_mips *c)
4032fa36399SKelvin Cheung {
4042fa36399SKelvin Cheung unsigned int config0;
4052f6f3136SJames Hogan int isa, mt;
4062fa36399SKelvin Cheung
4072fa36399SKelvin Cheung config0 = read_c0_config();
4082fa36399SKelvin Cheung
40975b5b5e0SLeonid Yegoshin /*
41075b5b5e0SLeonid Yegoshin * Look for Standard TLB or Dual VTLB and FTLB
41175b5b5e0SLeonid Yegoshin */
4122f6f3136SJames Hogan mt = config0 & MIPS_CONF_MT;
4132f6f3136SJames Hogan if (mt == MIPS_CONF_MT_TLB)
4142fa36399SKelvin Cheung c->options |= MIPS_CPU_TLB;
4152f6f3136SJames Hogan else if (mt == MIPS_CONF_MT_FTLB)
4162f6f3136SJames Hogan c->options |= MIPS_CPU_TLB | MIPS_CPU_FTLB;
41775b5b5e0SLeonid Yegoshin
4182fa36399SKelvin Cheung isa = (config0 & MIPS_CONF_AT) >> 13;
4192fa36399SKelvin Cheung switch (isa) {
4202fa36399SKelvin Cheung case 0:
4212fa36399SKelvin Cheung switch ((config0 & MIPS_CONF_AR) >> 10) {
4222fa36399SKelvin Cheung case 0:
423a96102beSSteven J. Hill set_isa(c, MIPS_CPU_ISA_M32R1);
4242fa36399SKelvin Cheung break;
4252fa36399SKelvin Cheung case 1:
426a96102beSSteven J. Hill set_isa(c, MIPS_CPU_ISA_M32R2);
4272fa36399SKelvin Cheung break;
4288b8aa636SLeonid Yegoshin case 2:
4298b8aa636SLeonid Yegoshin set_isa(c, MIPS_CPU_ISA_M32R6);
4308b8aa636SLeonid Yegoshin break;
4312fa36399SKelvin Cheung default:
4322fa36399SKelvin Cheung goto unknown;
4332fa36399SKelvin Cheung }
4342fa36399SKelvin Cheung break;
4352fa36399SKelvin Cheung case 2:
4362fa36399SKelvin Cheung switch ((config0 & MIPS_CONF_AR) >> 10) {
4372fa36399SKelvin Cheung case 0:
438a96102beSSteven J. Hill set_isa(c, MIPS_CPU_ISA_M64R1);
4392fa36399SKelvin Cheung break;
4402fa36399SKelvin Cheung case 1:
441a96102beSSteven J. Hill set_isa(c, MIPS_CPU_ISA_M64R2);
4422fa36399SKelvin Cheung break;
4438b8aa636SLeonid Yegoshin case 2:
4448b8aa636SLeonid Yegoshin set_isa(c, MIPS_CPU_ISA_M64R6);
4458b8aa636SLeonid Yegoshin break;
4462fa36399SKelvin Cheung default:
4472fa36399SKelvin Cheung goto unknown;
4482fa36399SKelvin Cheung }
4492fa36399SKelvin Cheung break;
4502fa36399SKelvin Cheung default:
4512fa36399SKelvin Cheung goto unknown;
4522fa36399SKelvin Cheung }
4532fa36399SKelvin Cheung
4542fa36399SKelvin Cheung return config0 & MIPS_CONF_M;
4552fa36399SKelvin Cheung
4562fa36399SKelvin Cheung unknown:
4572fa36399SKelvin Cheung panic(unknown_isa, config0);
4582fa36399SKelvin Cheung }
4592fa36399SKelvin Cheung
decode_config1(struct cpuinfo_mips * c)4602fa36399SKelvin Cheung static inline unsigned int decode_config1(struct cpuinfo_mips *c)
4612fa36399SKelvin Cheung {
4622fa36399SKelvin Cheung unsigned int config1;
4632fa36399SKelvin Cheung
4642fa36399SKelvin Cheung config1 = read_c0_config1();
4652fa36399SKelvin Cheung
4662fa36399SKelvin Cheung if (config1 & MIPS_CONF1_MD)
4672fa36399SKelvin Cheung c->ases |= MIPS_ASE_MDMX;
46830228c40SJames Hogan if (config1 & MIPS_CONF1_PC)
46930228c40SJames Hogan c->options |= MIPS_CPU_PERF;
4702fa36399SKelvin Cheung if (config1 & MIPS_CONF1_WR)
4712fa36399SKelvin Cheung c->options |= MIPS_CPU_WATCH;
4722fa36399SKelvin Cheung if (config1 & MIPS_CONF1_CA)
4732fa36399SKelvin Cheung c->ases |= MIPS_ASE_MIPS16;
4742fa36399SKelvin Cheung if (config1 & MIPS_CONF1_EP)
4752fa36399SKelvin Cheung c->options |= MIPS_CPU_EJTAG;
4762fa36399SKelvin Cheung if (config1 & MIPS_CONF1_FP) {
4772fa36399SKelvin Cheung c->options |= MIPS_CPU_FPU;
4782fa36399SKelvin Cheung c->options |= MIPS_CPU_32FPR;
4792fa36399SKelvin Cheung }
48075b5b5e0SLeonid Yegoshin if (cpu_has_tlb) {
4812fa36399SKelvin Cheung c->tlbsize = ((config1 & MIPS_CONF1_TLBS) >> 25) + 1;
48275b5b5e0SLeonid Yegoshin c->tlbsizevtlb = c->tlbsize;
48375b5b5e0SLeonid Yegoshin c->tlbsizeftlbsets = 0;
48475b5b5e0SLeonid Yegoshin }
4852fa36399SKelvin Cheung
4862fa36399SKelvin Cheung return config1 & MIPS_CONF_M;
4872fa36399SKelvin Cheung }
4882fa36399SKelvin Cheung
decode_config2(struct cpuinfo_mips * c)4892fa36399SKelvin Cheung static inline unsigned int decode_config2(struct cpuinfo_mips *c)
4902fa36399SKelvin Cheung {
4912fa36399SKelvin Cheung unsigned int config2;
4922fa36399SKelvin Cheung
4932fa36399SKelvin Cheung config2 = read_c0_config2();
4942fa36399SKelvin Cheung
4952fa36399SKelvin Cheung if (config2 & MIPS_CONF2_SL)
4962fa36399SKelvin Cheung c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT;
4972fa36399SKelvin Cheung
4982fa36399SKelvin Cheung return config2 & MIPS_CONF_M;
4992fa36399SKelvin Cheung }
5002fa36399SKelvin Cheung
decode_config3(struct cpuinfo_mips * c)5012fa36399SKelvin Cheung static inline unsigned int decode_config3(struct cpuinfo_mips *c)
5022fa36399SKelvin Cheung {
5032fa36399SKelvin Cheung unsigned int config3;
5042fa36399SKelvin Cheung
5052fa36399SKelvin Cheung config3 = read_c0_config3();
5062fa36399SKelvin Cheung
507b2ab4f08SSteven J. Hill if (config3 & MIPS_CONF3_SM) {
5082fa36399SKelvin Cheung c->ases |= MIPS_ASE_SMARTMIPS;
509f18bdfa1SJames Hogan c->options |= MIPS_CPU_RIXI | MIPS_CPU_CTXTC;
510b2ab4f08SSteven J. Hill }
511b2ab4f08SSteven J. Hill if (config3 & MIPS_CONF3_RXI)
512b2ab4f08SSteven J. Hill c->options |= MIPS_CPU_RIXI;
513f18bdfa1SJames Hogan if (config3 & MIPS_CONF3_CTXTC)
514f18bdfa1SJames Hogan c->options |= MIPS_CPU_CTXTC;
5152fa36399SKelvin Cheung if (config3 & MIPS_CONF3_DSP)
5162fa36399SKelvin Cheung c->ases |= MIPS_ASE_DSP;
517b5a6455cSZubair Lutfullah Kakakhel if (config3 & MIPS_CONF3_DSP2P) {
518ee80f7c7SSteven J. Hill c->ases |= MIPS_ASE_DSP2P;
519b5a6455cSZubair Lutfullah Kakakhel if (cpu_has_mips_r6)
520b5a6455cSZubair Lutfullah Kakakhel c->ases |= MIPS_ASE_DSP3;
521b5a6455cSZubair Lutfullah Kakakhel }
5222fa36399SKelvin Cheung if (config3 & MIPS_CONF3_VINT)
5232fa36399SKelvin Cheung c->options |= MIPS_CPU_VINT;
5242fa36399SKelvin Cheung if (config3 & MIPS_CONF3_VEIC)
5252fa36399SKelvin Cheung c->options |= MIPS_CPU_VEIC;
52612822570SJames Hogan if (config3 & MIPS_CONF3_LPA)
52712822570SJames Hogan c->options |= MIPS_CPU_LPA;
5282fa36399SKelvin Cheung if (config3 & MIPS_CONF3_MT)
5292fa36399SKelvin Cheung c->ases |= MIPS_ASE_MIPSMT;
5302fa36399SKelvin Cheung if (config3 & MIPS_CONF3_ULRI)
5312fa36399SKelvin Cheung c->options |= MIPS_CPU_ULRI;
532f8fa4811SSteven J. Hill if (config3 & MIPS_CONF3_ISA)
533f8fa4811SSteven J. Hill c->options |= MIPS_CPU_MICROMIPS;
5341e7decdbSDavid Daney if (config3 & MIPS_CONF3_VZ)
5351e7decdbSDavid Daney c->ases |= MIPS_ASE_VZ;
5364a0156fbSSteven J. Hill if (config3 & MIPS_CONF3_SC)
5374a0156fbSSteven J. Hill c->options |= MIPS_CPU_SEGMENTS;
538e06a1548SJames Hogan if (config3 & MIPS_CONF3_BI)
539e06a1548SJames Hogan c->options |= MIPS_CPU_BADINSTR;
540e06a1548SJames Hogan if (config3 & MIPS_CONF3_BP)
541e06a1548SJames Hogan c->options |= MIPS_CPU_BADINSTRP;
542a5e9a69eSPaul Burton if (config3 & MIPS_CONF3_MSA)
543a5e9a69eSPaul Burton c->ases |= MIPS_ASE_MSA;
544cab25bc7SPaul Burton if (config3 & MIPS_CONF3_PW) {
545ed4cbc81SMarkos Chandras c->htw_seq = 0;
5463d528b32SMarkos Chandras c->options |= MIPS_CPU_HTW;
547ed4cbc81SMarkos Chandras }
5489b3274bdSJames Hogan if (config3 & MIPS_CONF3_CDMM)
5499b3274bdSJames Hogan c->options |= MIPS_CPU_CDMM;
550aaa7be48SJames Hogan if (config3 & MIPS_CONF3_SP)
551aaa7be48SJames Hogan c->options |= MIPS_CPU_SP;
5522fa36399SKelvin Cheung
5532fa36399SKelvin Cheung return config3 & MIPS_CONF_M;
5542fa36399SKelvin Cheung }
5552fa36399SKelvin Cheung
decode_config4(struct cpuinfo_mips * c)5562fa36399SKelvin Cheung static inline unsigned int decode_config4(struct cpuinfo_mips *c)
5572fa36399SKelvin Cheung {
5582fa36399SKelvin Cheung unsigned int config4;
55975b5b5e0SLeonid Yegoshin unsigned int newcf4;
56075b5b5e0SLeonid Yegoshin unsigned int mmuextdef;
56175b5b5e0SLeonid Yegoshin unsigned int ftlb_page = MIPS_CONF4_FTLBPAGESIZE;
5622db003a5SPaul Burton unsigned long asid_mask;
5632fa36399SKelvin Cheung
5642fa36399SKelvin Cheung config4 = read_c0_config4();
5652fa36399SKelvin Cheung
5661745c1efSLeonid Yegoshin if (cpu_has_tlb) {
5671745c1efSLeonid Yegoshin if (((config4 & MIPS_CONF4_IE) >> 29) == 2)
5681745c1efSLeonid Yegoshin c->options |= MIPS_CPU_TLBINV;
56943d104dbSJames Hogan
570e87569cdSMarkos Chandras /*
57143d104dbSJames Hogan * R6 has dropped the MMUExtDef field from config4.
57243d104dbSJames Hogan * On R6 the fields always describe the FTLB, and only if it is
57343d104dbSJames Hogan * present according to Config.MT.
574e87569cdSMarkos Chandras */
57543d104dbSJames Hogan if (!cpu_has_mips_r6)
57643d104dbSJames Hogan mmuextdef = config4 & MIPS_CONF4_MMUEXTDEF;
57743d104dbSJames Hogan else if (cpu_has_ftlb)
578e87569cdSMarkos Chandras mmuextdef = MIPS_CONF4_MMUEXTDEF_VTLBSIZEEXT;
579e87569cdSMarkos Chandras else
58043d104dbSJames Hogan mmuextdef = 0;
581e87569cdSMarkos Chandras
58275b5b5e0SLeonid Yegoshin switch (mmuextdef) {
58375b5b5e0SLeonid Yegoshin case MIPS_CONF4_MMUEXTDEF_MMUSIZEEXT:
58475b5b5e0SLeonid Yegoshin c->tlbsize += (config4 & MIPS_CONF4_MMUSIZEEXT) * 0x40;
58575b5b5e0SLeonid Yegoshin c->tlbsizevtlb = c->tlbsize;
58675b5b5e0SLeonid Yegoshin break;
58775b5b5e0SLeonid Yegoshin case MIPS_CONF4_MMUEXTDEF_VTLBSIZEEXT:
58875b5b5e0SLeonid Yegoshin c->tlbsizevtlb +=
58975b5b5e0SLeonid Yegoshin ((config4 & MIPS_CONF4_VTLBSIZEEXT) >>
59075b5b5e0SLeonid Yegoshin MIPS_CONF4_VTLBSIZEEXT_SHIFT) * 0x40;
59175b5b5e0SLeonid Yegoshin c->tlbsize = c->tlbsizevtlb;
59275b5b5e0SLeonid Yegoshin ftlb_page = MIPS_CONF4_VFTLBPAGESIZE;
593c9b02990SLiangliang Huang fallthrough;
59475b5b5e0SLeonid Yegoshin case MIPS_CONF4_MMUEXTDEF_FTLBSIZEEXT:
59597f4ad29SMarkos Chandras if (mips_ftlb_disabled)
59697f4ad29SMarkos Chandras break;
59775b5b5e0SLeonid Yegoshin newcf4 = (config4 & ~ftlb_page) |
59875b5b5e0SLeonid Yegoshin (page_size_ftlb(mmuextdef) <<
59975b5b5e0SLeonid Yegoshin MIPS_CONF4_FTLBPAGESIZE_SHIFT);
60075b5b5e0SLeonid Yegoshin write_c0_config4(newcf4);
60175b5b5e0SLeonid Yegoshin back_to_back_c0_hazard();
60275b5b5e0SLeonid Yegoshin config4 = read_c0_config4();
60375b5b5e0SLeonid Yegoshin if (config4 != newcf4) {
60475b5b5e0SLeonid Yegoshin pr_err("PAGE_SIZE 0x%lx is not supported by FTLB (config4=0x%x)\n",
60575b5b5e0SLeonid Yegoshin PAGE_SIZE, config4);
60675b5b5e0SLeonid Yegoshin /* Switch FTLB off */
60775b5b5e0SLeonid Yegoshin set_ftlb_enable(c, 0);
608ebd0e0f5SPaul Burton mips_ftlb_disabled = 1;
60975b5b5e0SLeonid Yegoshin break;
61075b5b5e0SLeonid Yegoshin }
61175b5b5e0SLeonid Yegoshin c->tlbsizeftlbsets = 1 <<
61275b5b5e0SLeonid Yegoshin ((config4 & MIPS_CONF4_FTLBSETS) >>
61375b5b5e0SLeonid Yegoshin MIPS_CONF4_FTLBSETS_SHIFT);
61475b5b5e0SLeonid Yegoshin c->tlbsizeftlbways = ((config4 & MIPS_CONF4_FTLBWAYS) >>
61575b5b5e0SLeonid Yegoshin MIPS_CONF4_FTLBWAYS_SHIFT) + 2;
61675b5b5e0SLeonid Yegoshin c->tlbsize += c->tlbsizeftlbways * c->tlbsizeftlbsets;
61797f4ad29SMarkos Chandras mips_has_ftlb_configured = 1;
61875b5b5e0SLeonid Yegoshin break;
61975b5b5e0SLeonid Yegoshin }
6201745c1efSLeonid Yegoshin }
6211745c1efSLeonid Yegoshin
6229e575f75SJames Hogan c->kscratch_mask = (config4 & MIPS_CONF4_KSCREXIST)
6239e575f75SJames Hogan >> MIPS_CONF4_KSCREXIST_SHIFT;
6242fa36399SKelvin Cheung
6252db003a5SPaul Burton asid_mask = MIPS_ENTRYHI_ASID;
6262db003a5SPaul Burton if (config4 & MIPS_CONF4_AE)
6272db003a5SPaul Burton asid_mask |= MIPS_ENTRYHI_ASIDX;
6282db003a5SPaul Burton set_cpu_asid_mask(c, asid_mask);
6292db003a5SPaul Burton
6302db003a5SPaul Burton /*
6312db003a5SPaul Burton * Warn if the computed ASID mask doesn't match the mask the kernel
6322db003a5SPaul Burton * is built for. This may indicate either a serious problem or an
6332db003a5SPaul Burton * easy optimisation opportunity, but either way should be addressed.
6342db003a5SPaul Burton */
6352db003a5SPaul Burton WARN_ON(asid_mask != cpu_asid_mask(c));
6362db003a5SPaul Burton
6372fa36399SKelvin Cheung return config4 & MIPS_CONF_M;
6382fa36399SKelvin Cheung }
6392fa36399SKelvin Cheung
decode_config5(struct cpuinfo_mips * c)6408b8a7634SRalf Baechle static inline unsigned int decode_config5(struct cpuinfo_mips *c)
6418b8a7634SRalf Baechle {
642c8790d65SPaul Burton unsigned int config5, max_mmid_width;
643c8790d65SPaul Burton unsigned long asid_mask;
6448b8a7634SRalf Baechle
6458b8a7634SRalf Baechle config5 = read_c0_config5();
646d175ed2bSPaul Burton config5 &= ~(MIPS_CONF5_UFR | MIPS_CONF5_UFE);
647c8790d65SPaul Burton
648c8790d65SPaul Burton if (cpu_has_mips_r6) {
649c8790d65SPaul Burton if (!__builtin_constant_p(cpu_has_mmid) || cpu_has_mmid)
650c8790d65SPaul Burton config5 |= MIPS_CONF5_MI;
651c8790d65SPaul Burton else
652c8790d65SPaul Burton config5 &= ~MIPS_CONF5_MI;
653c8790d65SPaul Burton }
654c8790d65SPaul Burton
6558b8a7634SRalf Baechle write_c0_config5(config5);
6568b8a7634SRalf Baechle
65749016748SMarkos Chandras if (config5 & MIPS_CONF5_EVA)
65849016748SMarkos Chandras c->options |= MIPS_CPU_EVA;
6591f6c52ffSPaul Burton if (config5 & MIPS_CONF5_MRP)
6601f6c52ffSPaul Burton c->options |= MIPS_CPU_MAAR;
6615aed9da1SMarkos Chandras if (config5 & MIPS_CONF5_LLB)
6625aed9da1SMarkos Chandras c->options |= MIPS_CPU_RW_LLB;
663c5b36783SSteven J. Hill if (config5 & MIPS_CONF5_MVH)
6640f2d988dSJames Hogan c->options |= MIPS_CPU_MVH;
665f270d881SPaul Burton if (cpu_has_mips_r6 && (config5 & MIPS_CONF5_VP))
666f270d881SPaul Burton c->options |= MIPS_CPU_VP;
6678d1630f1SMaciej W. Rozycki if (config5 & MIPS_CONF5_CA2)
6688d1630f1SMaciej W. Rozycki c->ases |= MIPS_ASE_MIPS16E2;
66949016748SMarkos Chandras
670256211f2SMarcin Nowakowski if (config5 & MIPS_CONF5_CRCP)
671256211f2SMarcin Nowakowski elf_hwcap |= HWCAP_MIPS_CRC32;
672256211f2SMarcin Nowakowski
673c8790d65SPaul Burton if (cpu_has_mips_r6) {
674c8790d65SPaul Burton /* Ensure the write to config5 above takes effect */
675c8790d65SPaul Burton back_to_back_c0_hazard();
676c8790d65SPaul Burton
677c8790d65SPaul Burton /* Check whether we successfully enabled MMID support */
678c8790d65SPaul Burton config5 = read_c0_config5();
679c8790d65SPaul Burton if (config5 & MIPS_CONF5_MI)
680c8790d65SPaul Burton c->options |= MIPS_CPU_MMID;
681c8790d65SPaul Burton
682c8790d65SPaul Burton /*
683c8790d65SPaul Burton * Warn if we've hardcoded cpu_has_mmid to a value unsuitable
684c8790d65SPaul Burton * for the CPU we're running on, or if CPUs in an SMP system
685c8790d65SPaul Burton * have inconsistent MMID support.
686c8790d65SPaul Burton */
687c8790d65SPaul Burton WARN_ON(!!cpu_has_mmid != !!(config5 & MIPS_CONF5_MI));
688c8790d65SPaul Burton
689c8790d65SPaul Burton if (cpu_has_mmid) {
690c8790d65SPaul Burton write_c0_memorymapid(~0ul);
691c8790d65SPaul Burton back_to_back_c0_hazard();
692c8790d65SPaul Burton asid_mask = read_c0_memorymapid();
693c8790d65SPaul Burton
694c8790d65SPaul Burton /*
695c8790d65SPaul Burton * We maintain a bitmap to track MMID allocation, and
696c8790d65SPaul Burton * need a sensible upper bound on the size of that
697c8790d65SPaul Burton * bitmap. The initial CPU with MMID support (I6500)
698c8790d65SPaul Burton * supports 16 bit MMIDs, which gives us an 8KiB
699c8790d65SPaul Burton * bitmap. The architecture recommends that hardware
700c8790d65SPaul Burton * support 32 bit MMIDs, which would give us a 512MiB
701c8790d65SPaul Burton * bitmap - that's too big in most cases.
702c8790d65SPaul Burton *
703c8790d65SPaul Burton * Cap MMID width at 16 bits for now & we can revisit
704c8790d65SPaul Burton * this if & when hardware supports anything wider.
705c8790d65SPaul Burton */
706c8790d65SPaul Burton max_mmid_width = 16;
707c8790d65SPaul Burton if (asid_mask > GENMASK(max_mmid_width - 1, 0)) {
708c8790d65SPaul Burton pr_info("Capping MMID width at %d bits",
709c8790d65SPaul Burton max_mmid_width);
710c8790d65SPaul Burton asid_mask = GENMASK(max_mmid_width - 1, 0);
711c8790d65SPaul Burton }
712c8790d65SPaul Burton
713c8790d65SPaul Burton set_cpu_asid_mask(c, asid_mask);
714c8790d65SPaul Burton }
715c8790d65SPaul Burton }
716c8790d65SPaul Burton
7178b8a7634SRalf Baechle return config5 & MIPS_CONF_M;
7188b8a7634SRalf Baechle }
7198b8a7634SRalf Baechle
decode_configs(struct cpuinfo_mips * c)720078a55fcSPaul Gortmaker static void decode_configs(struct cpuinfo_mips *c)
7212fa36399SKelvin Cheung {
7222fa36399SKelvin Cheung int ok;
7232fa36399SKelvin Cheung
7242fa36399SKelvin Cheung /* MIPS32 or MIPS64 compliant CPU. */
7252fa36399SKelvin Cheung c->options = MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE | MIPS_CPU_COUNTER |
7262fa36399SKelvin Cheung MIPS_CPU_DIVEC | MIPS_CPU_LLSC | MIPS_CPU_MCHECK;
7272fa36399SKelvin Cheung
7282fa36399SKelvin Cheung c->scache.flags = MIPS_CACHE_NOT_PRESENT;
7292fa36399SKelvin Cheung
73097f4ad29SMarkos Chandras /* Enable FTLB if present and not disabled */
731ebd0e0f5SPaul Burton set_ftlb_enable(c, mips_ftlb_disabled ? 0 : FTLB_EN);
73275b5b5e0SLeonid Yegoshin
7332fa36399SKelvin Cheung ok = decode_config0(c); /* Read Config registers. */
7342fa36399SKelvin Cheung BUG_ON(!ok); /* Arch spec violation! */
7352fa36399SKelvin Cheung if (ok)
7362fa36399SKelvin Cheung ok = decode_config1(c);
7372fa36399SKelvin Cheung if (ok)
7382fa36399SKelvin Cheung ok = decode_config2(c);
7392fa36399SKelvin Cheung if (ok)
7402fa36399SKelvin Cheung ok = decode_config3(c);
7412fa36399SKelvin Cheung if (ok)
7422fa36399SKelvin Cheung ok = decode_config4(c);
7438b8a7634SRalf Baechle if (ok)
7448b8a7634SRalf Baechle ok = decode_config5(c);
7452fa36399SKelvin Cheung
74637fb60f8SJames Hogan /* Probe the EBase.WG bit */
74737fb60f8SJames Hogan if (cpu_has_mips_r2_r6) {
74837fb60f8SJames Hogan u64 ebase;
74937fb60f8SJames Hogan unsigned int status;
75037fb60f8SJames Hogan
75137fb60f8SJames Hogan /* {read,write}_c0_ebase_64() may be UNDEFINED prior to r6 */
75237fb60f8SJames Hogan ebase = cpu_has_mips64r6 ? read_c0_ebase_64()
75337fb60f8SJames Hogan : (s32)read_c0_ebase();
75437fb60f8SJames Hogan if (ebase & MIPS_EBASE_WG) {
75537fb60f8SJames Hogan /* WG bit already set, we can avoid the clumsy probe */
75637fb60f8SJames Hogan c->options |= MIPS_CPU_EBASE_WG;
75737fb60f8SJames Hogan } else {
75837fb60f8SJames Hogan /* Its UNDEFINED to change EBase while BEV=0 */
75937fb60f8SJames Hogan status = read_c0_status();
76037fb60f8SJames Hogan write_c0_status(status | ST0_BEV);
76137fb60f8SJames Hogan irq_enable_hazard();
76237fb60f8SJames Hogan /*
76337fb60f8SJames Hogan * On pre-r6 cores, this may well clobber the upper bits
76437fb60f8SJames Hogan * of EBase. This is hard to avoid without potentially
76537fb60f8SJames Hogan * hitting UNDEFINED dm*c0 behaviour if EBase is 32-bit.
76637fb60f8SJames Hogan */
76737fb60f8SJames Hogan if (cpu_has_mips64r6)
76837fb60f8SJames Hogan write_c0_ebase_64(ebase | MIPS_EBASE_WG);
76937fb60f8SJames Hogan else
77037fb60f8SJames Hogan write_c0_ebase(ebase | MIPS_EBASE_WG);
77137fb60f8SJames Hogan back_to_back_c0_hazard();
77237fb60f8SJames Hogan /* Restore BEV */
77337fb60f8SJames Hogan write_c0_status(status);
77437fb60f8SJames Hogan if (read_c0_ebase() & MIPS_EBASE_WG) {
77537fb60f8SJames Hogan c->options |= MIPS_CPU_EBASE_WG;
77637fb60f8SJames Hogan write_c0_ebase(ebase);
77737fb60f8SJames Hogan }
77837fb60f8SJames Hogan }
77937fb60f8SJames Hogan }
78037fb60f8SJames Hogan
781ebd0e0f5SPaul Burton /* configure the FTLB write probability */
782ebd0e0f5SPaul Burton set_ftlb_enable(c, (mips_ftlb_disabled ? 0 : FTLB_EN) | FTLB_SET_PROB);
783ebd0e0f5SPaul Burton
7842fa36399SKelvin Cheung mips_probe_watch_registers(c);
7852fa36399SKelvin Cheung
7860ee958e1SPaul Burton #ifndef CONFIG_MIPS_CPS
7878b8aa636SLeonid Yegoshin if (cpu_has_mips_r2_r6) {
788f875a832SPaul Burton unsigned int core;
789f875a832SPaul Burton
790f875a832SPaul Burton core = get_ebase_cpunum();
79130ee615bSPaul Burton if (cpu_has_mipsmt)
792f875a832SPaul Burton core >>= fls(core_nvpes()) - 1;
793f875a832SPaul Burton cpu_set_core(c, core);
79430ee615bSPaul Burton }
7950ee958e1SPaul Burton #endif
7962fa36399SKelvin Cheung }
7972fa36399SKelvin Cheung
7986ad816e7SJames Hogan /*
7996ad816e7SJames Hogan * Probe for certain guest capabilities by writing config bits and reading back.
8006ad816e7SJames Hogan * Finally write back the original value.
8016ad816e7SJames Hogan */
8026ad816e7SJames Hogan #define probe_gc0_config(name, maxconf, bits) \
8036ad816e7SJames Hogan do { \
8046ad816e7SJames Hogan unsigned int tmp; \
8056ad816e7SJames Hogan tmp = read_gc0_##name(); \
8066ad816e7SJames Hogan write_gc0_##name(tmp | (bits)); \
8076ad816e7SJames Hogan back_to_back_c0_hazard(); \
8086ad816e7SJames Hogan maxconf = read_gc0_##name(); \
8096ad816e7SJames Hogan write_gc0_##name(tmp); \
8106ad816e7SJames Hogan } while (0)
8116ad816e7SJames Hogan
8126ad816e7SJames Hogan /*
8136ad816e7SJames Hogan * Probe for dynamic guest capabilities by changing certain config bits and
8146ad816e7SJames Hogan * reading back to see if they change. Finally write back the original value.
8156ad816e7SJames Hogan */
8166ad816e7SJames Hogan #define probe_gc0_config_dyn(name, maxconf, dynconf, bits) \
8176ad816e7SJames Hogan do { \
8186ad816e7SJames Hogan maxconf = read_gc0_##name(); \
8196ad816e7SJames Hogan write_gc0_##name(maxconf ^ (bits)); \
8206ad816e7SJames Hogan back_to_back_c0_hazard(); \
8216ad816e7SJames Hogan dynconf = maxconf ^ read_gc0_##name(); \
8226ad816e7SJames Hogan write_gc0_##name(maxconf); \
8236ad816e7SJames Hogan maxconf |= dynconf; \
8246ad816e7SJames Hogan } while (0)
8256ad816e7SJames Hogan
decode_guest_config0(struct cpuinfo_mips * c)8266ad816e7SJames Hogan static inline unsigned int decode_guest_config0(struct cpuinfo_mips *c)
8276ad816e7SJames Hogan {
8286ad816e7SJames Hogan unsigned int config0;
8296ad816e7SJames Hogan
8306ad816e7SJames Hogan probe_gc0_config(config, config0, MIPS_CONF_M);
8316ad816e7SJames Hogan
8326ad816e7SJames Hogan if (config0 & MIPS_CONF_M)
8336ad816e7SJames Hogan c->guest.conf |= BIT(1);
8346ad816e7SJames Hogan return config0 & MIPS_CONF_M;
8356ad816e7SJames Hogan }
8366ad816e7SJames Hogan
decode_guest_config1(struct cpuinfo_mips * c)8376ad816e7SJames Hogan static inline unsigned int decode_guest_config1(struct cpuinfo_mips *c)
8386ad816e7SJames Hogan {
8396ad816e7SJames Hogan unsigned int config1, config1_dyn;
8406ad816e7SJames Hogan
8416ad816e7SJames Hogan probe_gc0_config_dyn(config1, config1, config1_dyn,
8426ad816e7SJames Hogan MIPS_CONF_M | MIPS_CONF1_PC | MIPS_CONF1_WR |
8436ad816e7SJames Hogan MIPS_CONF1_FP);
8446ad816e7SJames Hogan
8456ad816e7SJames Hogan if (config1 & MIPS_CONF1_FP)
8466ad816e7SJames Hogan c->guest.options |= MIPS_CPU_FPU;
8476ad816e7SJames Hogan if (config1_dyn & MIPS_CONF1_FP)
8486ad816e7SJames Hogan c->guest.options_dyn |= MIPS_CPU_FPU;
8496ad816e7SJames Hogan
8506ad816e7SJames Hogan if (config1 & MIPS_CONF1_WR)
8516ad816e7SJames Hogan c->guest.options |= MIPS_CPU_WATCH;
8526ad816e7SJames Hogan if (config1_dyn & MIPS_CONF1_WR)
8536ad816e7SJames Hogan c->guest.options_dyn |= MIPS_CPU_WATCH;
8546ad816e7SJames Hogan
8556ad816e7SJames Hogan if (config1 & MIPS_CONF1_PC)
8566ad816e7SJames Hogan c->guest.options |= MIPS_CPU_PERF;
8576ad816e7SJames Hogan if (config1_dyn & MIPS_CONF1_PC)
8586ad816e7SJames Hogan c->guest.options_dyn |= MIPS_CPU_PERF;
8596ad816e7SJames Hogan
8606ad816e7SJames Hogan if (config1 & MIPS_CONF_M)
8616ad816e7SJames Hogan c->guest.conf |= BIT(2);
8626ad816e7SJames Hogan return config1 & MIPS_CONF_M;
8636ad816e7SJames Hogan }
8646ad816e7SJames Hogan
decode_guest_config2(struct cpuinfo_mips * c)8656ad816e7SJames Hogan static inline unsigned int decode_guest_config2(struct cpuinfo_mips *c)
8666ad816e7SJames Hogan {
8676ad816e7SJames Hogan unsigned int config2;
8686ad816e7SJames Hogan
8696ad816e7SJames Hogan probe_gc0_config(config2, config2, MIPS_CONF_M);
8706ad816e7SJames Hogan
8716ad816e7SJames Hogan if (config2 & MIPS_CONF_M)
8726ad816e7SJames Hogan c->guest.conf |= BIT(3);
8736ad816e7SJames Hogan return config2 & MIPS_CONF_M;
8746ad816e7SJames Hogan }
8756ad816e7SJames Hogan
decode_guest_config3(struct cpuinfo_mips * c)8766ad816e7SJames Hogan static inline unsigned int decode_guest_config3(struct cpuinfo_mips *c)
8776ad816e7SJames Hogan {
8786ad816e7SJames Hogan unsigned int config3, config3_dyn;
8796ad816e7SJames Hogan
8806ad816e7SJames Hogan probe_gc0_config_dyn(config3, config3, config3_dyn,
881a7c7ad6cSJames Hogan MIPS_CONF_M | MIPS_CONF3_MSA | MIPS_CONF3_ULRI |
882a7c7ad6cSJames Hogan MIPS_CONF3_CTXTC);
8836ad816e7SJames Hogan
8846ad816e7SJames Hogan if (config3 & MIPS_CONF3_CTXTC)
8856ad816e7SJames Hogan c->guest.options |= MIPS_CPU_CTXTC;
8866ad816e7SJames Hogan if (config3_dyn & MIPS_CONF3_CTXTC)
8876ad816e7SJames Hogan c->guest.options_dyn |= MIPS_CPU_CTXTC;
8886ad816e7SJames Hogan
8896ad816e7SJames Hogan if (config3 & MIPS_CONF3_PW)
8906ad816e7SJames Hogan c->guest.options |= MIPS_CPU_HTW;
8916ad816e7SJames Hogan
892a7c7ad6cSJames Hogan if (config3 & MIPS_CONF3_ULRI)
893a7c7ad6cSJames Hogan c->guest.options |= MIPS_CPU_ULRI;
894a7c7ad6cSJames Hogan
8956ad816e7SJames Hogan if (config3 & MIPS_CONF3_SC)
8966ad816e7SJames Hogan c->guest.options |= MIPS_CPU_SEGMENTS;
8976ad816e7SJames Hogan
8986ad816e7SJames Hogan if (config3 & MIPS_CONF3_BI)
8996ad816e7SJames Hogan c->guest.options |= MIPS_CPU_BADINSTR;
9006ad816e7SJames Hogan if (config3 & MIPS_CONF3_BP)
9016ad816e7SJames Hogan c->guest.options |= MIPS_CPU_BADINSTRP;
9026ad816e7SJames Hogan
9036ad816e7SJames Hogan if (config3 & MIPS_CONF3_MSA)
9046ad816e7SJames Hogan c->guest.ases |= MIPS_ASE_MSA;
9056ad816e7SJames Hogan if (config3_dyn & MIPS_CONF3_MSA)
9066ad816e7SJames Hogan c->guest.ases_dyn |= MIPS_ASE_MSA;
9076ad816e7SJames Hogan
9086ad816e7SJames Hogan if (config3 & MIPS_CONF_M)
9096ad816e7SJames Hogan c->guest.conf |= BIT(4);
9106ad816e7SJames Hogan return config3 & MIPS_CONF_M;
9116ad816e7SJames Hogan }
9126ad816e7SJames Hogan
decode_guest_config4(struct cpuinfo_mips * c)9136ad816e7SJames Hogan static inline unsigned int decode_guest_config4(struct cpuinfo_mips *c)
9146ad816e7SJames Hogan {
9156ad816e7SJames Hogan unsigned int config4;
9166ad816e7SJames Hogan
9176ad816e7SJames Hogan probe_gc0_config(config4, config4,
9186ad816e7SJames Hogan MIPS_CONF_M | MIPS_CONF4_KSCREXIST);
9196ad816e7SJames Hogan
9206ad816e7SJames Hogan c->guest.kscratch_mask = (config4 & MIPS_CONF4_KSCREXIST)
9216ad816e7SJames Hogan >> MIPS_CONF4_KSCREXIST_SHIFT;
9226ad816e7SJames Hogan
9236ad816e7SJames Hogan if (config4 & MIPS_CONF_M)
9246ad816e7SJames Hogan c->guest.conf |= BIT(5);
9256ad816e7SJames Hogan return config4 & MIPS_CONF_M;
9266ad816e7SJames Hogan }
9276ad816e7SJames Hogan
decode_guest_config5(struct cpuinfo_mips * c)9286ad816e7SJames Hogan static inline unsigned int decode_guest_config5(struct cpuinfo_mips *c)
9296ad816e7SJames Hogan {
9306ad816e7SJames Hogan unsigned int config5, config5_dyn;
9316ad816e7SJames Hogan
9326ad816e7SJames Hogan probe_gc0_config_dyn(config5, config5, config5_dyn,
933a929bdc5SJames Hogan MIPS_CONF_M | MIPS_CONF5_MVH | MIPS_CONF5_MRP);
9346ad816e7SJames Hogan
9356ad816e7SJames Hogan if (config5 & MIPS_CONF5_MRP)
9366ad816e7SJames Hogan c->guest.options |= MIPS_CPU_MAAR;
9376ad816e7SJames Hogan if (config5_dyn & MIPS_CONF5_MRP)
9386ad816e7SJames Hogan c->guest.options_dyn |= MIPS_CPU_MAAR;
9396ad816e7SJames Hogan
9406ad816e7SJames Hogan if (config5 & MIPS_CONF5_LLB)
9416ad816e7SJames Hogan c->guest.options |= MIPS_CPU_RW_LLB;
9426ad816e7SJames Hogan
943a929bdc5SJames Hogan if (config5 & MIPS_CONF5_MVH)
944a929bdc5SJames Hogan c->guest.options |= MIPS_CPU_MVH;
945a929bdc5SJames Hogan
9466ad816e7SJames Hogan if (config5 & MIPS_CONF_M)
9476ad816e7SJames Hogan c->guest.conf |= BIT(6);
9486ad816e7SJames Hogan return config5 & MIPS_CONF_M;
9496ad816e7SJames Hogan }
9506ad816e7SJames Hogan
decode_guest_configs(struct cpuinfo_mips * c)9516ad816e7SJames Hogan static inline void decode_guest_configs(struct cpuinfo_mips *c)
9526ad816e7SJames Hogan {
9536ad816e7SJames Hogan unsigned int ok;
9546ad816e7SJames Hogan
9556ad816e7SJames Hogan ok = decode_guest_config0(c);
9566ad816e7SJames Hogan if (ok)
9576ad816e7SJames Hogan ok = decode_guest_config1(c);
9586ad816e7SJames Hogan if (ok)
9596ad816e7SJames Hogan ok = decode_guest_config2(c);
9606ad816e7SJames Hogan if (ok)
9616ad816e7SJames Hogan ok = decode_guest_config3(c);
9626ad816e7SJames Hogan if (ok)
9636ad816e7SJames Hogan ok = decode_guest_config4(c);
9646ad816e7SJames Hogan if (ok)
9656ad816e7SJames Hogan decode_guest_config5(c);
9666ad816e7SJames Hogan }
9676ad816e7SJames Hogan
cpu_probe_guestctl0(struct cpuinfo_mips * c)9686ad816e7SJames Hogan static inline void cpu_probe_guestctl0(struct cpuinfo_mips *c)
9696ad816e7SJames Hogan {
9706ad816e7SJames Hogan unsigned int guestctl0, temp;
9716ad816e7SJames Hogan
9726ad816e7SJames Hogan guestctl0 = read_c0_guestctl0();
9736ad816e7SJames Hogan
9746ad816e7SJames Hogan if (guestctl0 & MIPS_GCTL0_G0E)
9756ad816e7SJames Hogan c->options |= MIPS_CPU_GUESTCTL0EXT;
9766ad816e7SJames Hogan if (guestctl0 & MIPS_GCTL0_G1)
9776ad816e7SJames Hogan c->options |= MIPS_CPU_GUESTCTL1;
9786ad816e7SJames Hogan if (guestctl0 & MIPS_GCTL0_G2)
9796ad816e7SJames Hogan c->options |= MIPS_CPU_GUESTCTL2;
9806ad816e7SJames Hogan if (!(guestctl0 & MIPS_GCTL0_RAD)) {
9816ad816e7SJames Hogan c->options |= MIPS_CPU_GUESTID;
9826ad816e7SJames Hogan
9836ad816e7SJames Hogan /*
9846ad816e7SJames Hogan * Probe for Direct Root to Guest (DRG). Set GuestCtl1.RID = 0
9856ad816e7SJames Hogan * first, otherwise all data accesses will be fully virtualised
9866ad816e7SJames Hogan * as if they were performed by guest mode.
9876ad816e7SJames Hogan */
9886ad816e7SJames Hogan write_c0_guestctl1(0);
9896ad816e7SJames Hogan tlbw_use_hazard();
9906ad816e7SJames Hogan
9916ad816e7SJames Hogan write_c0_guestctl0(guestctl0 | MIPS_GCTL0_DRG);
9926ad816e7SJames Hogan back_to_back_c0_hazard();
9936ad816e7SJames Hogan temp = read_c0_guestctl0();
9946ad816e7SJames Hogan
9956ad816e7SJames Hogan if (temp & MIPS_GCTL0_DRG) {
9966ad816e7SJames Hogan write_c0_guestctl0(guestctl0);
9976ad816e7SJames Hogan c->options |= MIPS_CPU_DRG;
9986ad816e7SJames Hogan }
9996ad816e7SJames Hogan }
10006ad816e7SJames Hogan }
10016ad816e7SJames Hogan
cpu_probe_guestctl1(struct cpuinfo_mips * c)10026ad816e7SJames Hogan static inline void cpu_probe_guestctl1(struct cpuinfo_mips *c)
10036ad816e7SJames Hogan {
10046ad816e7SJames Hogan if (cpu_has_guestid) {
10056ad816e7SJames Hogan /* determine the number of bits of GuestID available */
10066ad816e7SJames Hogan write_c0_guestctl1(MIPS_GCTL1_ID);
10076ad816e7SJames Hogan back_to_back_c0_hazard();
10086ad816e7SJames Hogan c->guestid_mask = (read_c0_guestctl1() & MIPS_GCTL1_ID)
10096ad816e7SJames Hogan >> MIPS_GCTL1_ID_SHIFT;
10106ad816e7SJames Hogan write_c0_guestctl1(0);
10116ad816e7SJames Hogan }
10126ad816e7SJames Hogan }
10136ad816e7SJames Hogan
cpu_probe_gtoffset(struct cpuinfo_mips * c)10146ad816e7SJames Hogan static inline void cpu_probe_gtoffset(struct cpuinfo_mips *c)
10156ad816e7SJames Hogan {
10166ad816e7SJames Hogan /* determine the number of bits of GTOffset available */
10176ad816e7SJames Hogan write_c0_gtoffset(0xffffffff);
10186ad816e7SJames Hogan back_to_back_c0_hazard();
10196ad816e7SJames Hogan c->gtoffset_mask = read_c0_gtoffset();
10206ad816e7SJames Hogan write_c0_gtoffset(0);
10216ad816e7SJames Hogan }
10226ad816e7SJames Hogan
cpu_probe_vz(struct cpuinfo_mips * c)10236ad816e7SJames Hogan static inline void cpu_probe_vz(struct cpuinfo_mips *c)
10246ad816e7SJames Hogan {
10256ad816e7SJames Hogan cpu_probe_guestctl0(c);
10266ad816e7SJames Hogan if (cpu_has_guestctl1)
10276ad816e7SJames Hogan cpu_probe_guestctl1(c);
10286ad816e7SJames Hogan
10296ad816e7SJames Hogan cpu_probe_gtoffset(c);
10306ad816e7SJames Hogan
10316ad816e7SJames Hogan decode_guest_configs(c);
10326ad816e7SJames Hogan }
10336ad816e7SJames Hogan
103402cf2119SRalf Baechle #define R4K_OPTS (MIPS_CPU_TLB | MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE \
10351da177e4SLinus Torvalds | MIPS_CPU_COUNTER)
10361da177e4SLinus Torvalds
cpu_probe_legacy(struct cpuinfo_mips * c,unsigned int cpu)1037cea7e2dfSRalf Baechle static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
10381da177e4SLinus Torvalds {
10398ff374b9SMaciej W. Rozycki switch (c->processor_id & PRID_IMP_MASK) {
10401da177e4SLinus Torvalds case PRID_IMP_R2000:
10411da177e4SLinus Torvalds c->cputype = CPU_R2000;
1042cea7e2dfSRalf Baechle __cpu_name[cpu] = "R2000";
10439b26616cSMaciej W. Rozycki c->fpu_msk31 |= FPU_CSR_CONDX | FPU_CSR_FS;
104402cf2119SRalf Baechle c->options = MIPS_CPU_TLB | MIPS_CPU_3K_CACHE |
104502cf2119SRalf Baechle MIPS_CPU_NOFPUEX;
10461da177e4SLinus Torvalds if (__cpu_has_fpu())
10471da177e4SLinus Torvalds c->options |= MIPS_CPU_FPU;
10481da177e4SLinus Torvalds c->tlbsize = 64;
10491da177e4SLinus Torvalds break;
10501da177e4SLinus Torvalds case PRID_IMP_R3000:
10518ff374b9SMaciej W. Rozycki if ((c->processor_id & PRID_REV_MASK) == PRID_REV_R3000A) {
1052cea7e2dfSRalf Baechle if (cpu_has_confreg()) {
10531da177e4SLinus Torvalds c->cputype = CPU_R3081E;
1054cea7e2dfSRalf Baechle __cpu_name[cpu] = "R3081";
1055cea7e2dfSRalf Baechle } else {
10561da177e4SLinus Torvalds c->cputype = CPU_R3000A;
1057cea7e2dfSRalf Baechle __cpu_name[cpu] = "R3000A";
1058cea7e2dfSRalf Baechle }
1059cea7e2dfSRalf Baechle } else {
10601da177e4SLinus Torvalds c->cputype = CPU_R3000;
1061cea7e2dfSRalf Baechle __cpu_name[cpu] = "R3000";
1062cea7e2dfSRalf Baechle }
10639b26616cSMaciej W. Rozycki c->fpu_msk31 |= FPU_CSR_CONDX | FPU_CSR_FS;
106402cf2119SRalf Baechle c->options = MIPS_CPU_TLB | MIPS_CPU_3K_CACHE |
106502cf2119SRalf Baechle MIPS_CPU_NOFPUEX;
10661da177e4SLinus Torvalds if (__cpu_has_fpu())
10671da177e4SLinus Torvalds c->options |= MIPS_CPU_FPU;
10681da177e4SLinus Torvalds c->tlbsize = 64;
10691da177e4SLinus Torvalds break;
10701da177e4SLinus Torvalds case PRID_IMP_R4000:
10711da177e4SLinus Torvalds if (read_c0_config() & CONF_SC) {
10728ff374b9SMaciej W. Rozycki if ((c->processor_id & PRID_REV_MASK) >=
10738ff374b9SMaciej W. Rozycki PRID_REV_R4400) {
10741da177e4SLinus Torvalds c->cputype = CPU_R4400PC;
1075cea7e2dfSRalf Baechle __cpu_name[cpu] = "R4400PC";
10761da177e4SLinus Torvalds } else {
1077cea7e2dfSRalf Baechle c->cputype = CPU_R4000PC;
1078cea7e2dfSRalf Baechle __cpu_name[cpu] = "R4000PC";
1079cea7e2dfSRalf Baechle }
1080cea7e2dfSRalf Baechle } else {
10817f177a52SMaciej W. Rozycki int cca = read_c0_config() & CONF_CM_CMASK;
10827f177a52SMaciej W. Rozycki int mc;
10837f177a52SMaciej W. Rozycki
10847f177a52SMaciej W. Rozycki /*
10857f177a52SMaciej W. Rozycki * SC and MC versions can't be reliably told apart,
10867f177a52SMaciej W. Rozycki * but only the latter support coherent caching
10877f177a52SMaciej W. Rozycki * modes so assume the firmware has set the KSEG0
10887f177a52SMaciej W. Rozycki * coherency attribute reasonably (if uncached, we
10897f177a52SMaciej W. Rozycki * assume SC).
10907f177a52SMaciej W. Rozycki */
10917f177a52SMaciej W. Rozycki switch (cca) {
10927f177a52SMaciej W. Rozycki case CONF_CM_CACHABLE_CE:
10937f177a52SMaciej W. Rozycki case CONF_CM_CACHABLE_COW:
10947f177a52SMaciej W. Rozycki case CONF_CM_CACHABLE_CUW:
10957f177a52SMaciej W. Rozycki mc = 1;
10967f177a52SMaciej W. Rozycki break;
10977f177a52SMaciej W. Rozycki default:
10987f177a52SMaciej W. Rozycki mc = 0;
10997f177a52SMaciej W. Rozycki break;
11007f177a52SMaciej W. Rozycki }
11018ff374b9SMaciej W. Rozycki if ((c->processor_id & PRID_REV_MASK) >=
11028ff374b9SMaciej W. Rozycki PRID_REV_R4400) {
11037f177a52SMaciej W. Rozycki c->cputype = mc ? CPU_R4400MC : CPU_R4400SC;
11047f177a52SMaciej W. Rozycki __cpu_name[cpu] = mc ? "R4400MC" : "R4400SC";
1105cea7e2dfSRalf Baechle } else {
11067f177a52SMaciej W. Rozycki c->cputype = mc ? CPU_R4000MC : CPU_R4000SC;
11077f177a52SMaciej W. Rozycki __cpu_name[cpu] = mc ? "R4000MC" : "R4000SC";
1108cea7e2dfSRalf Baechle }
11091da177e4SLinus Torvalds }
11101da177e4SLinus Torvalds
1111a96102beSSteven J. Hill set_isa(c, MIPS_CPU_ISA_III);
11129b26616cSMaciej W. Rozycki c->fpu_msk31 |= FPU_CSR_CONDX;
11131da177e4SLinus Torvalds c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
11141da177e4SLinus Torvalds MIPS_CPU_WATCH | MIPS_CPU_VCE |
11151da177e4SLinus Torvalds MIPS_CPU_LLSC;
11161da177e4SLinus Torvalds c->tlbsize = 48;
11171da177e4SLinus Torvalds break;
111865ce6197SLauri Kasanen case PRID_IMP_R4300:
111965ce6197SLauri Kasanen c->cputype = CPU_R4300;
112065ce6197SLauri Kasanen __cpu_name[cpu] = "R4300";
112165ce6197SLauri Kasanen set_isa(c, MIPS_CPU_ISA_III);
112265ce6197SLauri Kasanen c->fpu_msk31 |= FPU_CSR_CONDX;
112365ce6197SLauri Kasanen c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
112465ce6197SLauri Kasanen MIPS_CPU_LLSC;
112565ce6197SLauri Kasanen c->tlbsize = 32;
112665ce6197SLauri Kasanen break;
11271da177e4SLinus Torvalds case PRID_IMP_R4600:
11281da177e4SLinus Torvalds c->cputype = CPU_R4600;
1129cea7e2dfSRalf Baechle __cpu_name[cpu] = "R4600";
1130a96102beSSteven J. Hill set_isa(c, MIPS_CPU_ISA_III);
11319b26616cSMaciej W. Rozycki c->fpu_msk31 |= FPU_CSR_CONDX;
1132075e7502SThiemo Seufer c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
1133075e7502SThiemo Seufer MIPS_CPU_LLSC;
11341da177e4SLinus Torvalds c->tlbsize = 48;
11351da177e4SLinus Torvalds break;
11361da177e4SLinus Torvalds #if 0
11371da177e4SLinus Torvalds case PRID_IMP_R4650:
11381da177e4SLinus Torvalds /*
11391da177e4SLinus Torvalds * This processor doesn't have an MMU, so it's not
11401da177e4SLinus Torvalds * "real easy" to run Linux on it. It is left purely
11411da177e4SLinus Torvalds * for documentation. Commented out because it shares
11421da177e4SLinus Torvalds * it's c0_prid id number with the TX3900.
11431da177e4SLinus Torvalds */
11441da177e4SLinus Torvalds c->cputype = CPU_R4650;
1145cea7e2dfSRalf Baechle __cpu_name[cpu] = "R4650";
1146a96102beSSteven J. Hill set_isa(c, MIPS_CPU_ISA_III);
11479b26616cSMaciej W. Rozycki c->fpu_msk31 |= FPU_CSR_CONDX;
11481da177e4SLinus Torvalds c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_LLSC;
11491da177e4SLinus Torvalds c->tlbsize = 48;
11501da177e4SLinus Torvalds break;
11511da177e4SLinus Torvalds #endif
11521da177e4SLinus Torvalds case PRID_IMP_R4700:
11531da177e4SLinus Torvalds c->cputype = CPU_R4700;
1154cea7e2dfSRalf Baechle __cpu_name[cpu] = "R4700";
1155a96102beSSteven J. Hill set_isa(c, MIPS_CPU_ISA_III);
11569b26616cSMaciej W. Rozycki c->fpu_msk31 |= FPU_CSR_CONDX;
11571da177e4SLinus Torvalds c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
11581da177e4SLinus Torvalds MIPS_CPU_LLSC;
11591da177e4SLinus Torvalds c->tlbsize = 48;
11601da177e4SLinus Torvalds break;
11611da177e4SLinus Torvalds case PRID_IMP_TX49:
11621da177e4SLinus Torvalds c->cputype = CPU_TX49XX;
1163cea7e2dfSRalf Baechle __cpu_name[cpu] = "R49XX";
1164a96102beSSteven J. Hill set_isa(c, MIPS_CPU_ISA_III);
11659b26616cSMaciej W. Rozycki c->fpu_msk31 |= FPU_CSR_CONDX;
11661da177e4SLinus Torvalds c->options = R4K_OPTS | MIPS_CPU_LLSC;
11671da177e4SLinus Torvalds if (!(c->processor_id & 0x08))
11681da177e4SLinus Torvalds c->options |= MIPS_CPU_FPU | MIPS_CPU_32FPR;
11691da177e4SLinus Torvalds c->tlbsize = 48;
11701da177e4SLinus Torvalds break;
11711da177e4SLinus Torvalds case PRID_IMP_R5000:
11721da177e4SLinus Torvalds c->cputype = CPU_R5000;
1173cea7e2dfSRalf Baechle __cpu_name[cpu] = "R5000";
1174a96102beSSteven J. Hill set_isa(c, MIPS_CPU_ISA_IV);
11751da177e4SLinus Torvalds c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
11761da177e4SLinus Torvalds MIPS_CPU_LLSC;
11771da177e4SLinus Torvalds c->tlbsize = 48;
11781da177e4SLinus Torvalds break;
11791da177e4SLinus Torvalds case PRID_IMP_R5500:
11801da177e4SLinus Torvalds c->cputype = CPU_R5500;
1181cea7e2dfSRalf Baechle __cpu_name[cpu] = "R5500";
1182a96102beSSteven J. Hill set_isa(c, MIPS_CPU_ISA_IV);
11831da177e4SLinus Torvalds c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
11841da177e4SLinus Torvalds MIPS_CPU_WATCH | MIPS_CPU_LLSC;
11851da177e4SLinus Torvalds c->tlbsize = 48;
11861da177e4SLinus Torvalds break;
11871da177e4SLinus Torvalds case PRID_IMP_NEVADA:
11881da177e4SLinus Torvalds c->cputype = CPU_NEVADA;
1189cea7e2dfSRalf Baechle __cpu_name[cpu] = "Nevada";
1190a96102beSSteven J. Hill set_isa(c, MIPS_CPU_ISA_IV);
11911da177e4SLinus Torvalds c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
11921da177e4SLinus Torvalds MIPS_CPU_DIVEC | MIPS_CPU_LLSC;
11931da177e4SLinus Torvalds c->tlbsize = 48;
11941da177e4SLinus Torvalds break;
11951da177e4SLinus Torvalds case PRID_IMP_RM7000:
11961da177e4SLinus Torvalds c->cputype = CPU_RM7000;
1197cea7e2dfSRalf Baechle __cpu_name[cpu] = "RM7000";
1198a96102beSSteven J. Hill set_isa(c, MIPS_CPU_ISA_IV);
11991da177e4SLinus Torvalds c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
12001da177e4SLinus Torvalds MIPS_CPU_LLSC;
12011da177e4SLinus Torvalds /*
12021da177e4SLinus Torvalds * Undocumented RM7000: Bit 29 in the info register of
12031da177e4SLinus Torvalds * the RM7000 v2.0 indicates if the TLB has 48 or 64
12041da177e4SLinus Torvalds * entries.
12051da177e4SLinus Torvalds *
12061da177e4SLinus Torvalds * 29 1 => 64 entry JTLB
12071da177e4SLinus Torvalds * 0 => 48 entry JTLB
12081da177e4SLinus Torvalds */
12091da177e4SLinus Torvalds c->tlbsize = (read_c0_info() & (1 << 29)) ? 64 : 48;
12101da177e4SLinus Torvalds break;
12111da177e4SLinus Torvalds case PRID_IMP_R10000:
12121da177e4SLinus Torvalds c->cputype = CPU_R10000;
1213cea7e2dfSRalf Baechle __cpu_name[cpu] = "R10000";
1214a96102beSSteven J. Hill set_isa(c, MIPS_CPU_ISA_IV);
12158b36612aSRalf Baechle c->options = MIPS_CPU_TLB | MIPS_CPU_4K_CACHE | MIPS_CPU_4KEX |
12161da177e4SLinus Torvalds MIPS_CPU_FPU | MIPS_CPU_32FPR |
12171da177e4SLinus Torvalds MIPS_CPU_COUNTER | MIPS_CPU_WATCH |
12181da177e4SLinus Torvalds MIPS_CPU_LLSC;
12191da177e4SLinus Torvalds c->tlbsize = 64;
12201da177e4SLinus Torvalds break;
12211da177e4SLinus Torvalds case PRID_IMP_R12000:
12221da177e4SLinus Torvalds c->cputype = CPU_R12000;
1223cea7e2dfSRalf Baechle __cpu_name[cpu] = "R12000";
1224a96102beSSteven J. Hill set_isa(c, MIPS_CPU_ISA_IV);
12258b36612aSRalf Baechle c->options = MIPS_CPU_TLB | MIPS_CPU_4K_CACHE | MIPS_CPU_4KEX |
12261da177e4SLinus Torvalds MIPS_CPU_FPU | MIPS_CPU_32FPR |
12271da177e4SLinus Torvalds MIPS_CPU_COUNTER | MIPS_CPU_WATCH |
122820cc5b64SThomas Bogendoerfer MIPS_CPU_LLSC;
12291da177e4SLinus Torvalds c->tlbsize = 64;
123020cc5b64SThomas Bogendoerfer write_c0_r10k_diag(read_c0_r10k_diag() | R10K_DIAG_E_GHIST);
12311da177e4SLinus Torvalds break;
123244d921b2SKumba case PRID_IMP_R14000:
123330577391SJoshua Kinard if (((c->processor_id >> 4) & 0x0f) > 2) {
123430577391SJoshua Kinard c->cputype = CPU_R16000;
123530577391SJoshua Kinard __cpu_name[cpu] = "R16000";
123630577391SJoshua Kinard } else {
123744d921b2SKumba c->cputype = CPU_R14000;
1238cea7e2dfSRalf Baechle __cpu_name[cpu] = "R14000";
123930577391SJoshua Kinard }
1240a96102beSSteven J. Hill set_isa(c, MIPS_CPU_ISA_IV);
124144d921b2SKumba c->options = MIPS_CPU_TLB | MIPS_CPU_4K_CACHE | MIPS_CPU_4KEX |
124244d921b2SKumba MIPS_CPU_FPU | MIPS_CPU_32FPR |
124344d921b2SKumba MIPS_CPU_COUNTER | MIPS_CPU_WATCH |
124420cc5b64SThomas Bogendoerfer MIPS_CPU_LLSC;
124544d921b2SKumba c->tlbsize = 64;
124620cc5b64SThomas Bogendoerfer write_c0_r10k_diag(read_c0_r10k_diag() | R10K_DIAG_E_GHIST);
124744d921b2SKumba break;
12487507445bSHuacai Chen case PRID_IMP_LOONGSON_64C: /* Loongson-2/3 */
12495aac1e8aSRobert Millan switch (c->processor_id & PRID_REV_MASK) {
12505aac1e8aSRobert Millan case PRID_REV_LOONGSON2E:
1251268a2d60SJiaxun Yang c->cputype = CPU_LOONGSON2EF;
1252c579d310SHuacai Chen __cpu_name[cpu] = "ICT Loongson-2";
12535aac1e8aSRobert Millan set_elf_platform(cpu, "loongson2e");
12547352c8b1SHuacai Chen set_isa(c, MIPS_CPU_ISA_III);
12559b26616cSMaciej W. Rozycki c->fpu_msk31 |= FPU_CSR_CONDX;
12565aac1e8aSRobert Millan break;
12575aac1e8aSRobert Millan case PRID_REV_LOONGSON2F:
1258268a2d60SJiaxun Yang c->cputype = CPU_LOONGSON2EF;
1259c579d310SHuacai Chen __cpu_name[cpu] = "ICT Loongson-2";
12605aac1e8aSRobert Millan set_elf_platform(cpu, "loongson2f");
12617352c8b1SHuacai Chen set_isa(c, MIPS_CPU_ISA_III);
12629b26616cSMaciej W. Rozycki c->fpu_msk31 |= FPU_CSR_CONDX;
12635aac1e8aSRobert Millan break;
1264b2edcfc8SHuacai Chen case PRID_REV_LOONGSON3A_R1:
1265268a2d60SJiaxun Yang c->cputype = CPU_LOONGSON64;
1266c579d310SHuacai Chen __cpu_name[cpu] = "ICT Loongson-3";
1267c579d310SHuacai Chen set_elf_platform(cpu, "loongson3a");
12687352c8b1SHuacai Chen set_isa(c, MIPS_CPU_ISA_M64R1);
1269d2f96554SJiaxun Yang c->ases |= (MIPS_ASE_LOONGSON_MMI | MIPS_ASE_LOONGSON_CAM |
1270d2f96554SJiaxun Yang MIPS_ASE_LOONGSON_EXT);
1271c579d310SHuacai Chen break;
1272e7841be5SHuacai Chen case PRID_REV_LOONGSON3B_R1:
1273e7841be5SHuacai Chen case PRID_REV_LOONGSON3B_R2:
1274268a2d60SJiaxun Yang c->cputype = CPU_LOONGSON64;
1275e7841be5SHuacai Chen __cpu_name[cpu] = "ICT Loongson-3";
1276e7841be5SHuacai Chen set_elf_platform(cpu, "loongson3b");
12777352c8b1SHuacai Chen set_isa(c, MIPS_CPU_ISA_M64R1);
1278d2f96554SJiaxun Yang c->ases |= (MIPS_ASE_LOONGSON_MMI | MIPS_ASE_LOONGSON_CAM |
1279d2f96554SJiaxun Yang MIPS_ASE_LOONGSON_EXT);
1280e7841be5SHuacai Chen break;
12815aac1e8aSRobert Millan }
12825aac1e8aSRobert Millan
12832a21c730SFuxin Zhang c->options = R4K_OPTS |
12842a21c730SFuxin Zhang MIPS_CPU_FPU | MIPS_CPU_LLSC |
12852a21c730SFuxin Zhang MIPS_CPU_32FPR;
12862a21c730SFuxin Zhang c->tlbsize = 64;
12877507445bSHuacai Chen set_cpu_asid_mask(c, MIPS_ENTRYHI_ASID);
1288cc94ea31SHuacai Chen c->writecombine = _CACHE_UNCACHED_ACCELERATED;
12892a21c730SFuxin Zhang break;
129026859198SHuacai Chen case PRID_IMP_LOONGSON_32: /* Loongson-1 */
12912fa36399SKelvin Cheung decode_configs(c);
12921da177e4SLinus Torvalds
1293b2afb64cSHuacai Chen c->cputype = CPU_LOONGSON32;
1294b4672d37SRalf Baechle
12952fa36399SKelvin Cheung switch (c->processor_id & PRID_REV_MASK) {
12962fa36399SKelvin Cheung case PRID_REV_LOONGSON1B:
12972fa36399SKelvin Cheung __cpu_name[cpu] = "Loongson 1B";
12984194318cSRalf Baechle break;
12992fa36399SKelvin Cheung }
13002fa36399SKelvin Cheung
13014194318cSRalf Baechle break;
1302b4672d37SRalf Baechle }
13031da177e4SLinus Torvalds }
13041da177e4SLinus Torvalds
cpu_probe_mips(struct cpuinfo_mips * c,unsigned int cpu)1305cea7e2dfSRalf Baechle static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu)
13061da177e4SLinus Torvalds {
13074f12b91dSMarkos Chandras c->writecombine = _CACHE_UNCACHED_ACCELERATED;
13088ff374b9SMaciej W. Rozycki switch (c->processor_id & PRID_IMP_MASK) {
1309b2498af5SLeonid Yegoshin case PRID_IMP_QEMU_GENERIC:
1310b2498af5SLeonid Yegoshin c->writecombine = _CACHE_UNCACHED;
1311b2498af5SLeonid Yegoshin c->cputype = CPU_QEMU_GENERIC;
1312b2498af5SLeonid Yegoshin __cpu_name[cpu] = "MIPS GENERIC QEMU";
1313b2498af5SLeonid Yegoshin break;
13141da177e4SLinus Torvalds case PRID_IMP_4KC:
13151da177e4SLinus Torvalds c->cputype = CPU_4KC;
13164f12b91dSMarkos Chandras c->writecombine = _CACHE_UNCACHED;
1317cea7e2dfSRalf Baechle __cpu_name[cpu] = "MIPS 4Kc";
13181da177e4SLinus Torvalds break;
13191da177e4SLinus Torvalds case PRID_IMP_4KEC:
13202b07bd02SRalf Baechle case PRID_IMP_4KECR2:
13212b07bd02SRalf Baechle c->cputype = CPU_4KEC;
13224f12b91dSMarkos Chandras c->writecombine = _CACHE_UNCACHED;
1323cea7e2dfSRalf Baechle __cpu_name[cpu] = "MIPS 4KEc";
13242b07bd02SRalf Baechle break;
13251da177e4SLinus Torvalds case PRID_IMP_4KSC:
13268afcb5d8SRalf Baechle case PRID_IMP_4KSD:
13271da177e4SLinus Torvalds c->cputype = CPU_4KSC;
13284f12b91dSMarkos Chandras c->writecombine = _CACHE_UNCACHED;
1329cea7e2dfSRalf Baechle __cpu_name[cpu] = "MIPS 4KSc";
13301da177e4SLinus Torvalds break;
13311da177e4SLinus Torvalds case PRID_IMP_5KC:
13321da177e4SLinus Torvalds c->cputype = CPU_5KC;
13334f12b91dSMarkos Chandras c->writecombine = _CACHE_UNCACHED;
1334cea7e2dfSRalf Baechle __cpu_name[cpu] = "MIPS 5Kc";
13351da177e4SLinus Torvalds break;
133678d4803fSLeonid Yegoshin case PRID_IMP_5KE:
133778d4803fSLeonid Yegoshin c->cputype = CPU_5KE;
13384f12b91dSMarkos Chandras c->writecombine = _CACHE_UNCACHED;
133978d4803fSLeonid Yegoshin __cpu_name[cpu] = "MIPS 5KE";
134078d4803fSLeonid Yegoshin break;
13411da177e4SLinus Torvalds case PRID_IMP_20KC:
13421da177e4SLinus Torvalds c->cputype = CPU_20KC;
13434f12b91dSMarkos Chandras c->writecombine = _CACHE_UNCACHED;
1344cea7e2dfSRalf Baechle __cpu_name[cpu] = "MIPS 20Kc";
13451da177e4SLinus Torvalds break;
13461da177e4SLinus Torvalds case PRID_IMP_24K:
13471da177e4SLinus Torvalds c->cputype = CPU_24K;
13484f12b91dSMarkos Chandras c->writecombine = _CACHE_UNCACHED;
1349cea7e2dfSRalf Baechle __cpu_name[cpu] = "MIPS 24Kc";
13501da177e4SLinus Torvalds break;
135142f3caefSJohn Crispin case PRID_IMP_24KE:
135242f3caefSJohn Crispin c->cputype = CPU_24K;
13534f12b91dSMarkos Chandras c->writecombine = _CACHE_UNCACHED;
135442f3caefSJohn Crispin __cpu_name[cpu] = "MIPS 24KEc";
135542f3caefSJohn Crispin break;
13561da177e4SLinus Torvalds case PRID_IMP_25KF:
13571da177e4SLinus Torvalds c->cputype = CPU_25KF;
13584f12b91dSMarkos Chandras c->writecombine = _CACHE_UNCACHED;
1359cea7e2dfSRalf Baechle __cpu_name[cpu] = "MIPS 25Kc";
13601da177e4SLinus Torvalds break;
1361bbc7f22fSRalf Baechle case PRID_IMP_34K:
1362bbc7f22fSRalf Baechle c->cputype = CPU_34K;
13634f12b91dSMarkos Chandras c->writecombine = _CACHE_UNCACHED;
1364cea7e2dfSRalf Baechle __cpu_name[cpu] = "MIPS 34Kc";
13658270ab48SMatt Redfearn cpu_set_mt_per_tc_perf(c);
1366bbc7f22fSRalf Baechle break;
1367c620953cSChris Dearman case PRID_IMP_74K:
1368c620953cSChris Dearman c->cputype = CPU_74K;
13694f12b91dSMarkos Chandras c->writecombine = _CACHE_UNCACHED;
1370cea7e2dfSRalf Baechle __cpu_name[cpu] = "MIPS 74Kc";
1371c620953cSChris Dearman break;
1372113c62d9SSteven J. Hill case PRID_IMP_M14KC:
1373113c62d9SSteven J. Hill c->cputype = CPU_M14KC;
13744f12b91dSMarkos Chandras c->writecombine = _CACHE_UNCACHED;
1375113c62d9SSteven J. Hill __cpu_name[cpu] = "MIPS M14Kc";
1376113c62d9SSteven J. Hill break;
1377f8fa4811SSteven J. Hill case PRID_IMP_M14KEC:
1378f8fa4811SSteven J. Hill c->cputype = CPU_M14KEC;
13794f12b91dSMarkos Chandras c->writecombine = _CACHE_UNCACHED;
1380f8fa4811SSteven J. Hill __cpu_name[cpu] = "MIPS M14KEc";
1381f8fa4811SSteven J. Hill break;
138239b8d525SRalf Baechle case PRID_IMP_1004K:
138339b8d525SRalf Baechle c->cputype = CPU_1004K;
13844f12b91dSMarkos Chandras c->writecombine = _CACHE_UNCACHED;
1385cea7e2dfSRalf Baechle __cpu_name[cpu] = "MIPS 1004Kc";
13868270ab48SMatt Redfearn cpu_set_mt_per_tc_perf(c);
138739b8d525SRalf Baechle break;
1388006a851bSSteven J. Hill case PRID_IMP_1074K:
1389442e14a2SSteven J. Hill c->cputype = CPU_1074K;
13904f12b91dSMarkos Chandras c->writecombine = _CACHE_UNCACHED;
1391006a851bSSteven J. Hill __cpu_name[cpu] = "MIPS 1074Kc";
1392006a851bSSteven J. Hill break;
1393b5f065e7SLeonid Yegoshin case PRID_IMP_INTERAPTIV_UP:
1394b5f065e7SLeonid Yegoshin c->cputype = CPU_INTERAPTIV;
1395b5f065e7SLeonid Yegoshin __cpu_name[cpu] = "MIPS interAptiv";
13968270ab48SMatt Redfearn cpu_set_mt_per_tc_perf(c);
1397b5f065e7SLeonid Yegoshin break;
1398b5f065e7SLeonid Yegoshin case PRID_IMP_INTERAPTIV_MP:
1399b5f065e7SLeonid Yegoshin c->cputype = CPU_INTERAPTIV;
1400b5f065e7SLeonid Yegoshin __cpu_name[cpu] = "MIPS interAptiv (multi)";
14018270ab48SMatt Redfearn cpu_set_mt_per_tc_perf(c);
1402b5f065e7SLeonid Yegoshin break;
1403b0d4d300SLeonid Yegoshin case PRID_IMP_PROAPTIV_UP:
1404b0d4d300SLeonid Yegoshin c->cputype = CPU_PROAPTIV;
1405b0d4d300SLeonid Yegoshin __cpu_name[cpu] = "MIPS proAptiv";
1406b0d4d300SLeonid Yegoshin break;
1407b0d4d300SLeonid Yegoshin case PRID_IMP_PROAPTIV_MP:
1408b0d4d300SLeonid Yegoshin c->cputype = CPU_PROAPTIV;
1409b0d4d300SLeonid Yegoshin __cpu_name[cpu] = "MIPS proAptiv (multi)";
1410b0d4d300SLeonid Yegoshin break;
1411829dcc0aSJames Hogan case PRID_IMP_P5600:
1412829dcc0aSJames Hogan c->cputype = CPU_P5600;
1413829dcc0aSJames Hogan __cpu_name[cpu] = "MIPS P5600";
1414829dcc0aSJames Hogan break;
1415eba20a3aSPaul Burton case PRID_IMP_P6600:
1416eba20a3aSPaul Burton c->cputype = CPU_P6600;
1417eba20a3aSPaul Burton __cpu_name[cpu] = "MIPS P6600";
1418eba20a3aSPaul Burton break;
1419e57f9a2dSMarkos Chandras case PRID_IMP_I6400:
1420e57f9a2dSMarkos Chandras c->cputype = CPU_I6400;
1421e57f9a2dSMarkos Chandras __cpu_name[cpu] = "MIPS I6400";
1422e57f9a2dSMarkos Chandras break;
1423859aeb1bSPaul Burton case PRID_IMP_I6500:
1424859aeb1bSPaul Burton c->cputype = CPU_I6500;
1425859aeb1bSPaul Burton __cpu_name[cpu] = "MIPS I6500";
1426859aeb1bSPaul Burton break;
14279943ed92SLeonid Yegoshin case PRID_IMP_M5150:
14289943ed92SLeonid Yegoshin c->cputype = CPU_M5150;
14299943ed92SLeonid Yegoshin __cpu_name[cpu] = "MIPS M5150";
14309943ed92SLeonid Yegoshin break;
143143aff742SPaul Burton case PRID_IMP_M6250:
143243aff742SPaul Burton c->cputype = CPU_M6250;
143343aff742SPaul Burton __cpu_name[cpu] = "MIPS M6250";
143443aff742SPaul Burton break;
14351da177e4SLinus Torvalds }
14360b6d497fSChris Dearman
143775b5b5e0SLeonid Yegoshin decode_configs(c);
143875b5b5e0SLeonid Yegoshin
14390b6d497fSChris Dearman spram_config();
1440e7bc8557SPaul Burton
1441742318adSSerge Semin mm_config(c);
1442742318adSSerge Semin
1443e7bc8557SPaul Burton switch (__get_cpu_type(c->cputype)) {
1444ab7c01fdSSerge Semin case CPU_M5150:
1445ab7c01fdSSerge Semin case CPU_P5600:
1446ab7c01fdSSerge Semin set_isa(c, MIPS_CPU_ISA_M32R5);
1447ab7c01fdSSerge Semin break;
1448e7bc8557SPaul Burton case CPU_I6500:
1449e7bc8557SPaul Burton c->options |= MIPS_CPU_SHARED_FTLB_ENTRIES;
1450c9b02990SLiangliang Huang fallthrough;
1451e7bc8557SPaul Burton case CPU_I6400:
1452e7bc8557SPaul Burton c->options |= MIPS_CPU_SHARED_FTLB_RAM;
1453c9b02990SLiangliang Huang fallthrough;
1454e7bc8557SPaul Burton default:
1455e7bc8557SPaul Burton break;
1456e7bc8557SPaul Burton }
1457efd1b4adSWANG Xuerui
1458efd1b4adSWANG Xuerui /* Recent MIPS cores use the implementation-dependent ExcCode 16 for
1459efd1b4adSWANG Xuerui * cache/FTLB parity exceptions.
1460efd1b4adSWANG Xuerui */
1461efd1b4adSWANG Xuerui switch (__get_cpu_type(c->cputype)) {
1462efd1b4adSWANG Xuerui case CPU_PROAPTIV:
1463efd1b4adSWANG Xuerui case CPU_P5600:
1464efd1b4adSWANG Xuerui case CPU_P6600:
1465efd1b4adSWANG Xuerui case CPU_I6400:
1466efd1b4adSWANG Xuerui case CPU_I6500:
1467efd1b4adSWANG Xuerui c->options |= MIPS_CPU_FTLBPAREX;
1468efd1b4adSWANG Xuerui break;
1469efd1b4adSWANG Xuerui }
14701da177e4SLinus Torvalds }
14711da177e4SLinus Torvalds
cpu_probe_alchemy(struct cpuinfo_mips * c,unsigned int cpu)1472cea7e2dfSRalf Baechle static inline void cpu_probe_alchemy(struct cpuinfo_mips *c, unsigned int cpu)
14731da177e4SLinus Torvalds {
14744194318cSRalf Baechle decode_configs(c);
14758ff374b9SMaciej W. Rozycki switch (c->processor_id & PRID_IMP_MASK) {
14761da177e4SLinus Torvalds case PRID_IMP_AU1_REV1:
14771da177e4SLinus Torvalds case PRID_IMP_AU1_REV2:
1478270717a8SManuel Lauss c->cputype = CPU_ALCHEMY;
14791da177e4SLinus Torvalds switch ((c->processor_id >> 24) & 0xff) {
14801da177e4SLinus Torvalds case 0:
1481cea7e2dfSRalf Baechle __cpu_name[cpu] = "Au1000";
14821da177e4SLinus Torvalds break;
14831da177e4SLinus Torvalds case 1:
1484cea7e2dfSRalf Baechle __cpu_name[cpu] = "Au1500";
14851da177e4SLinus Torvalds break;
14861da177e4SLinus Torvalds case 2:
1487cea7e2dfSRalf Baechle __cpu_name[cpu] = "Au1100";
14881da177e4SLinus Torvalds break;
14891da177e4SLinus Torvalds case 3:
1490cea7e2dfSRalf Baechle __cpu_name[cpu] = "Au1550";
14911da177e4SLinus Torvalds break;
1492e3ad1c23SPete Popov case 4:
1493cea7e2dfSRalf Baechle __cpu_name[cpu] = "Au1200";
14948ff374b9SMaciej W. Rozycki if ((c->processor_id & PRID_REV_MASK) == 2)
1495cea7e2dfSRalf Baechle __cpu_name[cpu] = "Au1250";
1496237cfee1SManuel Lauss break;
1497237cfee1SManuel Lauss case 5:
1498cea7e2dfSRalf Baechle __cpu_name[cpu] = "Au1210";
1499e3ad1c23SPete Popov break;
15001da177e4SLinus Torvalds default:
1501270717a8SManuel Lauss __cpu_name[cpu] = "Au1xxx";
15021da177e4SLinus Torvalds break;
15031da177e4SLinus Torvalds }
15041da177e4SLinus Torvalds break;
1505f2041708SManuel Lauss case PRID_IMP_NETLOGIC_AU13XX:
1506f2041708SManuel Lauss c->cputype = CPU_ALCHEMY;
1507f2041708SManuel Lauss __cpu_name[cpu] = "Au1300";
1508f2041708SManuel Lauss break;
15091da177e4SLinus Torvalds }
15101da177e4SLinus Torvalds }
15111da177e4SLinus Torvalds
cpu_probe_sibyte(struct cpuinfo_mips * c,unsigned int cpu)1512cea7e2dfSRalf Baechle static inline void cpu_probe_sibyte(struct cpuinfo_mips *c, unsigned int cpu)
15131da177e4SLinus Torvalds {
15144194318cSRalf Baechle decode_configs(c);
151502cf2119SRalf Baechle
15164f12b91dSMarkos Chandras c->writecombine = _CACHE_UNCACHED_ACCELERATED;
15178ff374b9SMaciej W. Rozycki switch (c->processor_id & PRID_IMP_MASK) {
15181da177e4SLinus Torvalds case PRID_IMP_SB1:
15191da177e4SLinus Torvalds c->cputype = CPU_SB1;
1520cea7e2dfSRalf Baechle __cpu_name[cpu] = "SiByte SB1";
15211da177e4SLinus Torvalds /* FPU in pass1 is known to have issues. */
15228ff374b9SMaciej W. Rozycki if ((c->processor_id & PRID_REV_MASK) < 0x02)
15234194318cSRalf Baechle c->options &= ~(MIPS_CPU_FPU | MIPS_CPU_32FPR);
15241da177e4SLinus Torvalds break;
152593ce2f52SAndrew Isaacson case PRID_IMP_SB1A:
152693ce2f52SAndrew Isaacson c->cputype = CPU_SB1A;
1527cea7e2dfSRalf Baechle __cpu_name[cpu] = "SiByte SB1A";
152893ce2f52SAndrew Isaacson break;
15291da177e4SLinus Torvalds }
15301da177e4SLinus Torvalds }
15311da177e4SLinus Torvalds
cpu_probe_sandcraft(struct cpuinfo_mips * c,unsigned int cpu)1532cea7e2dfSRalf Baechle static inline void cpu_probe_sandcraft(struct cpuinfo_mips *c, unsigned int cpu)
15331da177e4SLinus Torvalds {
15344194318cSRalf Baechle decode_configs(c);
15358ff374b9SMaciej W. Rozycki switch (c->processor_id & PRID_IMP_MASK) {
15361da177e4SLinus Torvalds case PRID_IMP_SR71000:
15371da177e4SLinus Torvalds c->cputype = CPU_SR71000;
1538cea7e2dfSRalf Baechle __cpu_name[cpu] = "Sandcraft SR71000";
15391da177e4SLinus Torvalds c->scache.ways = 8;
15401da177e4SLinus Torvalds c->tlbsize = 64;
15411da177e4SLinus Torvalds break;
15421da177e4SLinus Torvalds }
15431da177e4SLinus Torvalds }
15441da177e4SLinus Torvalds
cpu_probe_nxp(struct cpuinfo_mips * c,unsigned int cpu)1545cea7e2dfSRalf Baechle static inline void cpu_probe_nxp(struct cpuinfo_mips *c, unsigned int cpu)
1546bdf21b18SPete Popov {
1547bdf21b18SPete Popov decode_configs(c);
15488ff374b9SMaciej W. Rozycki switch (c->processor_id & PRID_IMP_MASK) {
1549bdf21b18SPete Popov case PRID_IMP_PR4450:
1550bdf21b18SPete Popov c->cputype = CPU_PR4450;
1551cea7e2dfSRalf Baechle __cpu_name[cpu] = "Philips PR4450";
1552a96102beSSteven J. Hill set_isa(c, MIPS_CPU_ISA_M32R1);
1553bdf21b18SPete Popov break;
1554bdf21b18SPete Popov }
1555bdf21b18SPete Popov }
1556bdf21b18SPete Popov
cpu_probe_broadcom(struct cpuinfo_mips * c,unsigned int cpu)1557cea7e2dfSRalf Baechle static inline void cpu_probe_broadcom(struct cpuinfo_mips *c, unsigned int cpu)
15581c0c13ebSAurelien Jarno {
15591c0c13ebSAurelien Jarno decode_configs(c);
15608ff374b9SMaciej W. Rozycki switch (c->processor_id & PRID_IMP_MASK) {
1561190fca3eSKevin Cernekee case PRID_IMP_BMIPS32_REV4:
1562190fca3eSKevin Cernekee case PRID_IMP_BMIPS32_REV8:
1563602977b0SKevin Cernekee c->cputype = CPU_BMIPS32;
1564602977b0SKevin Cernekee __cpu_name[cpu] = "Broadcom BMIPS32";
156506785df0SKevin Cernekee set_elf_platform(cpu, "bmips32");
15661c0c13ebSAurelien Jarno break;
1567602977b0SKevin Cernekee case PRID_IMP_BMIPS3300:
1568602977b0SKevin Cernekee case PRID_IMP_BMIPS3300_ALT:
1569602977b0SKevin Cernekee case PRID_IMP_BMIPS3300_BUG:
1570602977b0SKevin Cernekee c->cputype = CPU_BMIPS3300;
1571602977b0SKevin Cernekee __cpu_name[cpu] = "Broadcom BMIPS3300";
157206785df0SKevin Cernekee set_elf_platform(cpu, "bmips3300");
1573bd67b711SThomas Bogendoerfer reserve_exception_space(0x400, VECTORSPACING * 64);
15741c0c13ebSAurelien Jarno break;
1575602977b0SKevin Cernekee case PRID_IMP_BMIPS43XX: {
15768ff374b9SMaciej W. Rozycki int rev = c->processor_id & PRID_REV_MASK;
1577602977b0SKevin Cernekee
1578602977b0SKevin Cernekee if (rev >= PRID_REV_BMIPS4380_LO &&
1579602977b0SKevin Cernekee rev <= PRID_REV_BMIPS4380_HI) {
1580602977b0SKevin Cernekee c->cputype = CPU_BMIPS4380;
1581602977b0SKevin Cernekee __cpu_name[cpu] = "Broadcom BMIPS4380";
158206785df0SKevin Cernekee set_elf_platform(cpu, "bmips4380");
1583b4720809SFlorian Fainelli c->options |= MIPS_CPU_RIXI;
1584bd67b711SThomas Bogendoerfer reserve_exception_space(0x400, VECTORSPACING * 64);
1585602977b0SKevin Cernekee } else {
1586602977b0SKevin Cernekee c->cputype = CPU_BMIPS4350;
1587602977b0SKevin Cernekee __cpu_name[cpu] = "Broadcom BMIPS4350";
158806785df0SKevin Cernekee set_elf_platform(cpu, "bmips4350");
1589602977b0SKevin Cernekee }
15900de663efSMaxime Bizon break;
15910de663efSMaxime Bizon }
1592602977b0SKevin Cernekee case PRID_IMP_BMIPS5000:
159368e6a783SKevin Cernekee case PRID_IMP_BMIPS5200:
1594602977b0SKevin Cernekee c->cputype = CPU_BMIPS5000;
159537808d62SFlorian Fainelli if ((c->processor_id & PRID_IMP_MASK) == PRID_IMP_BMIPS5200)
159637808d62SFlorian Fainelli __cpu_name[cpu] = "Broadcom BMIPS5200";
159737808d62SFlorian Fainelli else
1598602977b0SKevin Cernekee __cpu_name[cpu] = "Broadcom BMIPS5000";
159906785df0SKevin Cernekee set_elf_platform(cpu, "bmips5000");
1600b4720809SFlorian Fainelli c->options |= MIPS_CPU_ULRI | MIPS_CPU_RIXI;
1601bd67b711SThomas Bogendoerfer reserve_exception_space(0x1000, VECTORSPACING * 64);
1602602977b0SKevin Cernekee break;
16031c0c13ebSAurelien Jarno }
16041c0c13ebSAurelien Jarno }
16051c0c13ebSAurelien Jarno
cpu_probe_cavium(struct cpuinfo_mips * c,unsigned int cpu)16060dd4781bSDavid Daney static inline void cpu_probe_cavium(struct cpuinfo_mips *c, unsigned int cpu)
16070dd4781bSDavid Daney {
16080dd4781bSDavid Daney decode_configs(c);
1609918d7795SJiaxun Yang /* Octeon has different cache interface */
1610918d7795SJiaxun Yang c->options &= ~MIPS_CPU_4K_CACHE;
16118ff374b9SMaciej W. Rozycki switch (c->processor_id & PRID_IMP_MASK) {
16120dd4781bSDavid Daney case PRID_IMP_CAVIUM_CN38XX:
16130dd4781bSDavid Daney case PRID_IMP_CAVIUM_CN31XX:
16140dd4781bSDavid Daney case PRID_IMP_CAVIUM_CN30XX:
16156f329468SDavid Daney c->cputype = CPU_CAVIUM_OCTEON;
16166f329468SDavid Daney __cpu_name[cpu] = "Cavium Octeon";
16176f329468SDavid Daney goto platform;
16180dd4781bSDavid Daney case PRID_IMP_CAVIUM_CN58XX:
16190dd4781bSDavid Daney case PRID_IMP_CAVIUM_CN56XX:
16200dd4781bSDavid Daney case PRID_IMP_CAVIUM_CN50XX:
16210dd4781bSDavid Daney case PRID_IMP_CAVIUM_CN52XX:
16226f329468SDavid Daney c->cputype = CPU_CAVIUM_OCTEON_PLUS;
16236f329468SDavid Daney __cpu_name[cpu] = "Cavium Octeon+";
16246f329468SDavid Daney platform:
1625c094c99eSRobert Millan set_elf_platform(cpu, "octeon");
16260dd4781bSDavid Daney break;
1627a1431b61SDavid Daney case PRID_IMP_CAVIUM_CN61XX:
16280e56b385SDavid Daney case PRID_IMP_CAVIUM_CN63XX:
1629a1431b61SDavid Daney case PRID_IMP_CAVIUM_CN66XX:
1630a1431b61SDavid Daney case PRID_IMP_CAVIUM_CN68XX:
1631af04bb85SDavid Daney case PRID_IMP_CAVIUM_CNF71XX:
16320e56b385SDavid Daney c->cputype = CPU_CAVIUM_OCTEON2;
16330e56b385SDavid Daney __cpu_name[cpu] = "Cavium Octeon II";
1634c094c99eSRobert Millan set_elf_platform(cpu, "octeon2");
16350e56b385SDavid Daney break;
1636af04bb85SDavid Daney case PRID_IMP_CAVIUM_CN70XX:
1637b8c8f665SDavid Daney case PRID_IMP_CAVIUM_CN73XX:
1638b8c8f665SDavid Daney case PRID_IMP_CAVIUM_CNF75XX:
1639af04bb85SDavid Daney case PRID_IMP_CAVIUM_CN78XX:
1640af04bb85SDavid Daney c->cputype = CPU_CAVIUM_OCTEON3;
1641af04bb85SDavid Daney __cpu_name[cpu] = "Cavium Octeon III";
1642af04bb85SDavid Daney set_elf_platform(cpu, "octeon3");
1643af04bb85SDavid Daney break;
16440dd4781bSDavid Daney default:
16450dd4781bSDavid Daney printk(KERN_INFO "Unknown Octeon chip!\n");
16460dd4781bSDavid Daney c->cputype = CPU_UNKNOWN;
16470dd4781bSDavid Daney break;
16480dd4781bSDavid Daney }
16490dd4781bSDavid Daney }
16500dd4781bSDavid Daney
1651da1bd297SJiaxun Yang #ifdef CONFIG_CPU_LOONGSON64
1652da1bd297SJiaxun Yang #include <loongson_regs.h>
1653da1bd297SJiaxun Yang
decode_cpucfg(struct cpuinfo_mips * c)1654da1bd297SJiaxun Yang static inline void decode_cpucfg(struct cpuinfo_mips *c)
1655da1bd297SJiaxun Yang {
1656da1bd297SJiaxun Yang u32 cfg1 = read_cpucfg(LOONGSON_CFG1);
1657da1bd297SJiaxun Yang u32 cfg2 = read_cpucfg(LOONGSON_CFG2);
1658da1bd297SJiaxun Yang u32 cfg3 = read_cpucfg(LOONGSON_CFG3);
1659da1bd297SJiaxun Yang
1660da1bd297SJiaxun Yang if (cfg1 & LOONGSON_CFG1_MMI)
1661da1bd297SJiaxun Yang c->ases |= MIPS_ASE_LOONGSON_MMI;
1662da1bd297SJiaxun Yang
1663da1bd297SJiaxun Yang if (cfg2 & LOONGSON_CFG2_LEXT1)
1664da1bd297SJiaxun Yang c->ases |= MIPS_ASE_LOONGSON_EXT;
1665da1bd297SJiaxun Yang
1666da1bd297SJiaxun Yang if (cfg2 & LOONGSON_CFG2_LEXT2)
1667da1bd297SJiaxun Yang c->ases |= MIPS_ASE_LOONGSON_EXT2;
1668da1bd297SJiaxun Yang
16693210e2c2SHuacai Chen if (cfg2 & LOONGSON_CFG2_LSPW) {
1670da1bd297SJiaxun Yang c->options |= MIPS_CPU_LDPTE;
16713210e2c2SHuacai Chen c->guest.options |= MIPS_CPU_LDPTE;
16723210e2c2SHuacai Chen }
1673da1bd297SJiaxun Yang
1674da1bd297SJiaxun Yang if (cfg3 & LOONGSON_CFG3_LCAMP)
1675da1bd297SJiaxun Yang c->ases |= MIPS_ASE_LOONGSON_CAM;
1676da1bd297SJiaxun Yang }
1677da1bd297SJiaxun Yang
cpu_probe_loongson(struct cpuinfo_mips * c,unsigned int cpu)1678b2edcfc8SHuacai Chen static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu)
1679b2edcfc8SHuacai Chen {
168065fee014SHuacai Chen c->cputype = CPU_LOONGSON64;
168165fee014SHuacai Chen
1682bc6e8dc1SWANG Xuerui /* All Loongson processors covered here define ExcCode 16 as GSExc. */
168365fee014SHuacai Chen decode_configs(c);
1684bc6e8dc1SWANG Xuerui c->options |= MIPS_CPU_GSEXCEX;
1685bc6e8dc1SWANG Xuerui
1686b2edcfc8SHuacai Chen switch (c->processor_id & PRID_IMP_MASK) {
16870cf2ea11SJiaxun Yang case PRID_IMP_LOONGSON_64R: /* Loongson-64 Reduced */
16880cf2ea11SJiaxun Yang switch (c->processor_id & PRID_REV_MASK) {
16890cf2ea11SJiaxun Yang case PRID_REV_LOONGSON2K_R1_0:
16900cf2ea11SJiaxun Yang case PRID_REV_LOONGSON2K_R1_1:
16910cf2ea11SJiaxun Yang case PRID_REV_LOONGSON2K_R1_2:
16920cf2ea11SJiaxun Yang case PRID_REV_LOONGSON2K_R1_3:
16930cf2ea11SJiaxun Yang __cpu_name[cpu] = "Loongson-2K";
16940cf2ea11SJiaxun Yang set_elf_platform(cpu, "gs264e");
16950cf2ea11SJiaxun Yang set_isa(c, MIPS_CPU_ISA_M64R2);
16960cf2ea11SJiaxun Yang break;
16970cf2ea11SJiaxun Yang }
16980cf2ea11SJiaxun Yang c->ases |= (MIPS_ASE_LOONGSON_MMI | MIPS_ASE_LOONGSON_EXT |
16990cf2ea11SJiaxun Yang MIPS_ASE_LOONGSON_EXT2);
17000cf2ea11SJiaxun Yang break;
17010cf2ea11SJiaxun Yang case PRID_IMP_LOONGSON_64C: /* Loongson-3 Classic */
1702b2edcfc8SHuacai Chen switch (c->processor_id & PRID_REV_MASK) {
1703f3ade253SHuacai Chen case PRID_REV_LOONGSON3A_R2_0:
1704f3ade253SHuacai Chen case PRID_REV_LOONGSON3A_R2_1:
1705b2edcfc8SHuacai Chen __cpu_name[cpu] = "ICT Loongson-3";
1706b2edcfc8SHuacai Chen set_elf_platform(cpu, "loongson3a");
1707b2edcfc8SHuacai Chen set_isa(c, MIPS_CPU_ISA_M64R2);
1708b2edcfc8SHuacai Chen break;
17097cff3f16SHuacai Chen case PRID_REV_LOONGSON3A_R3_0:
17107cff3f16SHuacai Chen case PRID_REV_LOONGSON3A_R3_1:
17110a00024dSHuacai Chen __cpu_name[cpu] = "ICT Loongson-3";
17120a00024dSHuacai Chen set_elf_platform(cpu, "loongson3a");
17130a00024dSHuacai Chen set_isa(c, MIPS_CPU_ISA_M64R2);
17140a00024dSHuacai Chen break;
1715b2edcfc8SHuacai Chen }
1716da1bd297SJiaxun Yang /*
1717da1bd297SJiaxun Yang * Loongson-3 Classic did not implement MIPS standard TLBINV
1718da1bd297SJiaxun Yang * but implemented TLBINVF and EHINV. As currently we're only
1719da1bd297SJiaxun Yang * using these two features, enable MIPS_CPU_TLBINV as well.
17203aed240eSJiaxun Yang *
17213aed240eSJiaxun Yang * Also some early Loongson-3A2000 had wrong TLB type in Config
17223aed240eSJiaxun Yang * register, we correct it here.
1723da1bd297SJiaxun Yang */
17243aed240eSJiaxun Yang c->options |= MIPS_CPU_FTLB | MIPS_CPU_TLBINV | MIPS_CPU_LDPTE;
1725d2f96554SJiaxun Yang c->ases |= (MIPS_ASE_LOONGSON_MMI | MIPS_ASE_LOONGSON_CAM |
1726d2f96554SJiaxun Yang MIPS_ASE_LOONGSON_EXT | MIPS_ASE_LOONGSON_EXT2);
17270f78355cSHuacai Chen c->ases &= ~MIPS_ASE_VZ; /* VZ of Loongson-3A2000/3000 is incomplete */
1728*ac5d3bafSJiaxun Yang change_c0_config6(LOONGSON_CONF6_EXTIMER | LOONGSON_CONF6_INTIMER,
1729*ac5d3bafSJiaxun Yang LOONGSON_CONF6_INTIMER);
1730b2edcfc8SHuacai Chen break;
17317507445bSHuacai Chen case PRID_IMP_LOONGSON_64G:
17327507445bSHuacai Chen __cpu_name[cpu] = "ICT Loongson-3";
17337507445bSHuacai Chen set_elf_platform(cpu, "loongson3a");
17347507445bSHuacai Chen set_isa(c, MIPS_CPU_ISA_M64R2);
1735da1bd297SJiaxun Yang decode_cpucfg(c);
1736*ac5d3bafSJiaxun Yang change_c0_config6(LOONGSON_CONF6_EXTIMER | LOONGSON_CONF6_INTIMER,
1737*ac5d3bafSJiaxun Yang LOONGSON_CONF6_INTIMER);
17387507445bSHuacai Chen break;
1739b2edcfc8SHuacai Chen default:
1740b2edcfc8SHuacai Chen panic("Unknown Loongson Processor ID!");
1741b2edcfc8SHuacai Chen break;
1742b2edcfc8SHuacai Chen }
1743b2edcfc8SHuacai Chen }
1744da1bd297SJiaxun Yang #else
cpu_probe_loongson(struct cpuinfo_mips * c,unsigned int cpu)1745da1bd297SJiaxun Yang static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu) { }
1746da1bd297SJiaxun Yang #endif
1747b2edcfc8SHuacai Chen
cpu_probe_ingenic(struct cpuinfo_mips * c,unsigned int cpu)174883ccf69dSLars-Peter Clausen static inline void cpu_probe_ingenic(struct cpuinfo_mips *c, unsigned int cpu)
174983ccf69dSLars-Peter Clausen {
175083ccf69dSLars-Peter Clausen decode_configs(c);
1751368fb26cSPaul Cercueil
1752368fb26cSPaul Cercueil /*
1753368fb26cSPaul Cercueil * XBurst misses a config2 register, so config3 decode was skipped in
1754368fb26cSPaul Cercueil * decode_configs().
1755368fb26cSPaul Cercueil */
1756368fb26cSPaul Cercueil decode_config3(c);
1757368fb26cSPaul Cercueil
17583b25b763SPaul Cercueil /* XBurst does not implement the CP0 counter. */
175983ccf69dSLars-Peter Clausen c->options &= ~MIPS_CPU_COUNTER;
17605f5ed0ebSPaul Cercueil BUG_ON(__builtin_constant_p(cpu_has_counter) && cpu_has_counter);
1761368fb26cSPaul Cercueil
17625ef41510SPaul Cercueil /* XBurst has virtually tagged icache */
17635ef41510SPaul Cercueil c->icache.flags |= MIPS_CACHE_VTAG;
17645ef41510SPaul Cercueil
17658ff374b9SMaciej W. Rozycki switch (c->processor_id & PRID_IMP_MASK) {
17660d10d17bS周琰杰 (Zhou Yanjie)
17670d10d17bS周琰杰 (Zhou Yanjie) /* XBurst®1 with MXU1.0/MXU1.1 SIMD ISA */
1768b9bb868eS周琰杰 (Zhou Yanjie) case PRID_IMP_XBURST_REV1:
1769b9bb868eS周琰杰 (Zhou Yanjie)
1770053951ddSZhou Yanjie /*
1771053951ddSZhou Yanjie * The XBurst core by default attempts to avoid branch target
1772053951ddSZhou Yanjie * buffer lookups by detecting & special casing loops. This
1773053951ddSZhou Yanjie * feature will cause BogoMIPS and lpj calculate in error.
1774053951ddSZhou Yanjie * Set cp0 config7 bit 4 to disable this feature.
1775053951ddSZhou Yanjie */
1776053951ddSZhou Yanjie set_c0_config7(MIPS_CONF7_BTB_LOOP_EN);
17778041edb5SPaul Cercueil
1778b02efeb0SZhou Yanjie switch (c->processor_id & PRID_COMP_MASK) {
1779b9bb868eS周琰杰 (Zhou Yanjie)
1780b9bb868eS周琰杰 (Zhou Yanjie) /*
1781b9bb868eS周琰杰 (Zhou Yanjie) * The config0 register in the XBurst CPUs with a processor ID of
1782b9bb868eS周琰杰 (Zhou Yanjie) * PRID_COMP_INGENIC_D0 report themselves as MIPS32r2 compatible,
1783b9bb868eS周琰杰 (Zhou Yanjie) * but they don't actually support this ISA.
1784b9bb868eS周琰杰 (Zhou Yanjie) */
1785b9bb868eS周琰杰 (Zhou Yanjie) case PRID_COMP_INGENIC_D0:
1786b9bb868eS周琰杰 (Zhou Yanjie) c->isa_level &= ~MIPS_CPU_ISA_M32R2;
1787fc52f92aSPaul Cercueil
1788fc52f92aSPaul Cercueil /* FPU is not properly detected on JZ4760(B). */
1789fc52f92aSPaul Cercueil if (c->processor_id == 0x2ed0024f)
1790fc52f92aSPaul Cercueil c->options |= MIPS_CPU_FPU;
1791fc52f92aSPaul Cercueil
1792a5360958SPaul Cercueil fallthrough;
1793b9bb868eS周琰杰 (Zhou Yanjie)
17948041edb5SPaul Cercueil /*
1795b02efeb0SZhou Yanjie * The config0 register in the XBurst CPUs with a processor ID of
1796a5360958SPaul Cercueil * PRID_COMP_INGENIC_D0 or PRID_COMP_INGENIC_D1 has an abandoned
1797a5360958SPaul Cercueil * huge page tlb mode, this mode is not compatible with the MIPS
1798a5360958SPaul Cercueil * standard, it will cause tlbmiss and into an infinite loop
1799a5360958SPaul Cercueil * (line 21 in the tlb-funcs.S) when starting the init process.
1800a5360958SPaul Cercueil * After chip reset, the default is HPTLB mode, Write 0xa9000000
1801a5360958SPaul Cercueil * to cp0 register 5 sel 4 to switch back to VTLB mode to prevent
1802a5360958SPaul Cercueil * getting stuck.
1803b02efeb0SZhou Yanjie */
1804b02efeb0SZhou Yanjie case PRID_COMP_INGENIC_D1:
1805b02efeb0SZhou Yanjie write_c0_page_ctrl(XBURST_PAGECTRL_HPTLB_DIS);
1806b02efeb0SZhou Yanjie break;
1807b9bb868eS周琰杰 (Zhou Yanjie)
1808b02efeb0SZhou Yanjie default:
1809b02efeb0SZhou Yanjie break;
1810b02efeb0SZhou Yanjie }
1811c9b02990SLiangliang Huang fallthrough;
18120d10d17bS周琰杰 (Zhou Yanjie)
18130d10d17bS周琰杰 (Zhou Yanjie) /* XBurst®1 with MXU2.0 SIMD ISA */
1814b9bb868eS周琰杰 (Zhou Yanjie) case PRID_IMP_XBURST_REV2:
181595b1f6dbSPaul Cercueil /* Ingenic uses the WA bit to achieve write-combine memory writes */
181695b1f6dbSPaul Cercueil c->writecombine = _CACHE_CACHABLE_WA;
1817b9bb868eS周琰杰 (Zhou Yanjie) c->cputype = CPU_XBURST;
1818b9bb868eS周琰杰 (Zhou Yanjie) __cpu_name[cpu] = "Ingenic XBurst";
1819b9bb868eS周琰杰 (Zhou Yanjie) break;
1820b9bb868eS周琰杰 (Zhou Yanjie)
18210d10d17bS周琰杰 (Zhou Yanjie) /* XBurst®2 with MXU2.1 SIMD ISA */
18220d10d17bS周琰杰 (Zhou Yanjie) case PRID_IMP_XBURST2:
18230d10d17bS周琰杰 (Zhou Yanjie) c->cputype = CPU_XBURST;
18240d10d17bS周琰杰 (Zhou Yanjie) __cpu_name[cpu] = "Ingenic XBurst II";
18250d10d17bS周琰杰 (Zhou Yanjie) break;
18260d10d17bS周琰杰 (Zhou Yanjie)
1827b9bb868eS周琰杰 (Zhou Yanjie) default:
1828b9bb868eS周琰杰 (Zhou Yanjie) panic("Unknown Ingenic Processor ID!");
1829b9bb868eS周琰杰 (Zhou Yanjie) break;
1830b9bb868eS周琰杰 (Zhou Yanjie) }
183183ccf69dSLars-Peter Clausen }
183283ccf69dSLars-Peter Clausen
1833949e51beSDavid Daney #ifdef CONFIG_64BIT
1834949e51beSDavid Daney /* For use by uaccess.h */
1835949e51beSDavid Daney u64 __ua_limit;
1836949e51beSDavid Daney EXPORT_SYMBOL(__ua_limit);
1837949e51beSDavid Daney #endif
1838949e51beSDavid Daney
18399966db25SRalf Baechle const char *__cpu_name[NR_CPUS];
1840874fd3b5SDavid Daney const char *__elf_platform;
1841e585b768SYunQiang Su const char *__elf_base_platform;
18429966db25SRalf Baechle
cpu_probe(void)1843078a55fcSPaul Gortmaker void cpu_probe(void)
18441da177e4SLinus Torvalds {
18451da177e4SLinus Torvalds struct cpuinfo_mips *c = ¤t_cpu_data;
18469966db25SRalf Baechle unsigned int cpu = smp_processor_id();
18471da177e4SLinus Torvalds
184805510f2bSMarcin Nowakowski /*
184905510f2bSMarcin Nowakowski * Set a default elf platform, cpu probe may later
185005510f2bSMarcin Nowakowski * overwrite it with a more precise value
185105510f2bSMarcin Nowakowski */
185205510f2bSMarcin Nowakowski set_elf_platform(cpu, "mips");
185305510f2bSMarcin Nowakowski
18541da177e4SLinus Torvalds c->processor_id = PRID_IMP_UNKNOWN;
18551da177e4SLinus Torvalds c->fpu_id = FPIR_IMP_NONE;
18561da177e4SLinus Torvalds c->cputype = CPU_UNKNOWN;
18574f12b91dSMarkos Chandras c->writecombine = _CACHE_UNCACHED;
18581da177e4SLinus Torvalds
18599b26616cSMaciej W. Rozycki c->fpu_csr31 = FPU_CSR_RN;
18609b26616cSMaciej W. Rozycki c->fpu_msk31 = FPU_CSR_RSVD | FPU_CSR_ABS2008 | FPU_CSR_NAN2008;
18619b26616cSMaciej W. Rozycki
18621da177e4SLinus Torvalds c->processor_id = read_c0_prid();
18638ff374b9SMaciej W. Rozycki switch (c->processor_id & PRID_COMP_MASK) {
18641da177e4SLinus Torvalds case PRID_COMP_LEGACY:
1865cea7e2dfSRalf Baechle cpu_probe_legacy(c, cpu);
18661da177e4SLinus Torvalds break;
18671da177e4SLinus Torvalds case PRID_COMP_MIPS:
1868cea7e2dfSRalf Baechle cpu_probe_mips(c, cpu);
18691da177e4SLinus Torvalds break;
18701da177e4SLinus Torvalds case PRID_COMP_ALCHEMY:
1871f2041708SManuel Lauss case PRID_COMP_NETLOGIC:
1872cea7e2dfSRalf Baechle cpu_probe_alchemy(c, cpu);
18731da177e4SLinus Torvalds break;
18741da177e4SLinus Torvalds case PRID_COMP_SIBYTE:
1875cea7e2dfSRalf Baechle cpu_probe_sibyte(c, cpu);
18761da177e4SLinus Torvalds break;
18771c0c13ebSAurelien Jarno case PRID_COMP_BROADCOM:
1878cea7e2dfSRalf Baechle cpu_probe_broadcom(c, cpu);
18791c0c13ebSAurelien Jarno break;
18801da177e4SLinus Torvalds case PRID_COMP_SANDCRAFT:
1881cea7e2dfSRalf Baechle cpu_probe_sandcraft(c, cpu);
18821da177e4SLinus Torvalds break;
1883a92b0588SDaniel Laird case PRID_COMP_NXP:
1884cea7e2dfSRalf Baechle cpu_probe_nxp(c, cpu);
1885bdf21b18SPete Popov break;
18860dd4781bSDavid Daney case PRID_COMP_CAVIUM:
18870dd4781bSDavid Daney cpu_probe_cavium(c, cpu);
18880dd4781bSDavid Daney break;
1889b2edcfc8SHuacai Chen case PRID_COMP_LOONGSON:
1890b2edcfc8SHuacai Chen cpu_probe_loongson(c, cpu);
1891b2edcfc8SHuacai Chen break;
18920d10d17bS周琰杰 (Zhou Yanjie) case PRID_COMP_INGENIC_13:
1893252617a4SPaul Burton case PRID_COMP_INGENIC_D0:
1894252617a4SPaul Burton case PRID_COMP_INGENIC_D1:
1895252617a4SPaul Burton case PRID_COMP_INGENIC_E1:
189683ccf69dSLars-Peter Clausen cpu_probe_ingenic(c, cpu);
189783ccf69dSLars-Peter Clausen break;
18981da177e4SLinus Torvalds }
1899dec8b1caSFranck Bui-Huu
1900cea7e2dfSRalf Baechle BUG_ON(!__cpu_name[cpu]);
1901cea7e2dfSRalf Baechle BUG_ON(c->cputype == CPU_UNKNOWN);
1902cea7e2dfSRalf Baechle
1903dec8b1caSFranck Bui-Huu /*
1904dec8b1caSFranck Bui-Huu * Platform code can force the cpu type to optimize code
1905dec8b1caSFranck Bui-Huu * generation. In that case be sure the cpu type is correctly
1906dec8b1caSFranck Bui-Huu * manually setup otherwise it could trigger some nasty bugs.
1907dec8b1caSFranck Bui-Huu */
1908dec8b1caSFranck Bui-Huu BUG_ON(current_cpu_type() != c->cputype);
1909dec8b1caSFranck Bui-Huu
19102e274768SFlorian Fainelli if (cpu_has_rixi) {
19112e274768SFlorian Fainelli /* Enable the RIXI exceptions */
19122e274768SFlorian Fainelli set_c0_pagegrain(PG_IEC);
19132e274768SFlorian Fainelli back_to_back_c0_hazard();
19142e274768SFlorian Fainelli /* Verify the IEC bit is set */
19152e274768SFlorian Fainelli if (read_c0_pagegrain() & PG_IEC)
19162e274768SFlorian Fainelli c->options |= MIPS_CPU_RIXIEX;
19172e274768SFlorian Fainelli }
19182e274768SFlorian Fainelli
19190103d23fSKevin Cernekee if (mips_fpu_disabled)
19200103d23fSKevin Cernekee c->options &= ~MIPS_CPU_FPU;
19210103d23fSKevin Cernekee
19220103d23fSKevin Cernekee if (mips_dsp_disabled)
1923ee80f7c7SSteven J. Hill c->ases &= ~(MIPS_ASE_DSP | MIPS_ASE_DSP2P);
19240103d23fSKevin Cernekee
19253d528b32SMarkos Chandras if (mips_htw_disabled) {
19263d528b32SMarkos Chandras c->options &= ~MIPS_CPU_HTW;
19273d528b32SMarkos Chandras write_c0_pwctl(read_c0_pwctl() &
19283d528b32SMarkos Chandras ~(1 << MIPS_PWCTL_PWEN_SHIFT));
19293d528b32SMarkos Chandras }
19303d528b32SMarkos Chandras
19317aecd5caSMaciej W. Rozycki if (c->options & MIPS_CPU_FPU)
19327aecd5caSMaciej W. Rozycki cpu_set_fpu_opts(c);
19337aecd5caSMaciej W. Rozycki else
19347aecd5caSMaciej W. Rozycki cpu_set_nofpu_opts(c);
19359966db25SRalf Baechle
19368b8aa636SLeonid Yegoshin if (cpu_has_mips_r2_r6) {
1937f6771dbbSRalf Baechle c->srsets = ((read_c0_srsctl() >> 26) & 0x0f) + 1;
1938da4b62cdSAl Cooper /* R2 has Performance Counter Interrupt indicator */
1939da4b62cdSAl Cooper c->options |= MIPS_CPU_PCI;
1940da4b62cdSAl Cooper }
1941f6771dbbSRalf Baechle else
1942f6771dbbSRalf Baechle c->srsets = 1;
194391dfc423SGuenter Roeck
19444c063034SPaul Burton if (cpu_has_mips_r6)
19454c063034SPaul Burton elf_hwcap |= HWCAP_MIPS_R6;
19464c063034SPaul Burton
1947a8ad1367SPaul Burton if (cpu_has_msa) {
1948a5e9a69eSPaul Burton c->msa_id = cpu_get_msa_id();
1949a8ad1367SPaul Burton WARN(c->msa_id & MSA_IR_WRPF,
1950a8ad1367SPaul Burton "Vector register partitioning unimplemented!");
19513cc9fa7fSPaul Burton elf_hwcap |= HWCAP_MIPS_MSA;
1952a8ad1367SPaul Burton }
1953a5e9a69eSPaul Burton
195438dffe1eSJiaxun Yang if (cpu_has_mips16)
195538dffe1eSJiaxun Yang elf_hwcap |= HWCAP_MIPS_MIPS16;
195638dffe1eSJiaxun Yang
195738dffe1eSJiaxun Yang if (cpu_has_mdmx)
195838dffe1eSJiaxun Yang elf_hwcap |= HWCAP_MIPS_MDMX;
195938dffe1eSJiaxun Yang
196038dffe1eSJiaxun Yang if (cpu_has_mips3d)
196138dffe1eSJiaxun Yang elf_hwcap |= HWCAP_MIPS_MIPS3D;
196238dffe1eSJiaxun Yang
196338dffe1eSJiaxun Yang if (cpu_has_smartmips)
196438dffe1eSJiaxun Yang elf_hwcap |= HWCAP_MIPS_SMARTMIPS;
196538dffe1eSJiaxun Yang
196638dffe1eSJiaxun Yang if (cpu_has_dsp)
196738dffe1eSJiaxun Yang elf_hwcap |= HWCAP_MIPS_DSP;
196838dffe1eSJiaxun Yang
196938dffe1eSJiaxun Yang if (cpu_has_dsp2)
197038dffe1eSJiaxun Yang elf_hwcap |= HWCAP_MIPS_DSP2;
197138dffe1eSJiaxun Yang
197238dffe1eSJiaxun Yang if (cpu_has_dsp3)
197338dffe1eSJiaxun Yang elf_hwcap |= HWCAP_MIPS_DSP3;
197438dffe1eSJiaxun Yang
197538dffe1eSJiaxun Yang if (cpu_has_mips16e2)
197638dffe1eSJiaxun Yang elf_hwcap |= HWCAP_MIPS_MIPS16E2;
197738dffe1eSJiaxun Yang
197838dffe1eSJiaxun Yang if (cpu_has_loongson_mmi)
197938dffe1eSJiaxun Yang elf_hwcap |= HWCAP_LOONGSON_MMI;
198038dffe1eSJiaxun Yang
198138dffe1eSJiaxun Yang if (cpu_has_loongson_ext)
198238dffe1eSJiaxun Yang elf_hwcap |= HWCAP_LOONGSON_EXT;
198338dffe1eSJiaxun Yang
198438dffe1eSJiaxun Yang if (cpu_has_loongson_ext2)
198538dffe1eSJiaxun Yang elf_hwcap |= HWCAP_LOONGSON_EXT2;
198638dffe1eSJiaxun Yang
19876ad816e7SJames Hogan if (cpu_has_vz)
19886ad816e7SJames Hogan cpu_probe_vz(c);
19896ad816e7SJames Hogan
199091dfc423SGuenter Roeck cpu_probe_vmbits(c);
1991949e51beSDavid Daney
1992ec7a9318SWANG Xuerui /* Synthesize CPUCFG data if running on Loongson processors;
1993ec7a9318SWANG Xuerui * no-op otherwise.
1994ec7a9318SWANG Xuerui *
1995ec7a9318SWANG Xuerui * This looks at previously probed features, so keep this at bottom.
1996ec7a9318SWANG Xuerui */
1997ec7a9318SWANG Xuerui loongson3_cpucfg_synthesize_data(c);
1998ec7a9318SWANG Xuerui
1999949e51beSDavid Daney #ifdef CONFIG_64BIT
2000949e51beSDavid Daney if (cpu == 0)
2001949e51beSDavid Daney __ua_limit = ~((1ull << cpu_vmbits) - 1);
2002949e51beSDavid Daney #endif
2003bd67b711SThomas Bogendoerfer
2004bd67b711SThomas Bogendoerfer reserve_exception_space(0, 0x1000);
20051da177e4SLinus Torvalds }
20061da177e4SLinus Torvalds
cpu_report(void)2007078a55fcSPaul Gortmaker void cpu_report(void)
20081da177e4SLinus Torvalds {
20091da177e4SLinus Torvalds struct cpuinfo_mips *c = ¤t_cpu_data;
20101da177e4SLinus Torvalds
2011d9f897c9SLeonid Yegoshin pr_info("CPU%d revision is: %08x (%s)\n",
2012d9f897c9SLeonid Yegoshin smp_processor_id(), c->processor_id, cpu_name_string());
20131da177e4SLinus Torvalds if (c->options & MIPS_CPU_FPU)
20149966db25SRalf Baechle printk(KERN_INFO "FPU revision is: %08x\n", c->fpu_id);
2015a5e9a69eSPaul Burton if (cpu_has_msa)
2016a5e9a69eSPaul Burton pr_info("MSA revision is: %08x\n", c->msa_id);
20171da177e4SLinus Torvalds }
2018856fbceeSPaul Burton
cpu_set_cluster(struct cpuinfo_mips * cpuinfo,unsigned int cluster)20195616897eSPaul Burton void cpu_set_cluster(struct cpuinfo_mips *cpuinfo, unsigned int cluster)
20205616897eSPaul Burton {
20215616897eSPaul Burton /* Ensure the core number fits in the field */
20225616897eSPaul Burton WARN_ON(cluster > (MIPS_GLOBALNUMBER_CLUSTER >>
20235616897eSPaul Burton MIPS_GLOBALNUMBER_CLUSTER_SHF));
20245616897eSPaul Burton
20255616897eSPaul Burton cpuinfo->globalnumber &= ~MIPS_GLOBALNUMBER_CLUSTER;
20265616897eSPaul Burton cpuinfo->globalnumber |= cluster << MIPS_GLOBALNUMBER_CLUSTER_SHF;
20275616897eSPaul Burton }
20285616897eSPaul Burton
cpu_set_core(struct cpuinfo_mips * cpuinfo,unsigned int core)2029856fbceeSPaul Burton void cpu_set_core(struct cpuinfo_mips *cpuinfo, unsigned int core)
2030856fbceeSPaul Burton {
2031856fbceeSPaul Burton /* Ensure the core number fits in the field */
2032856fbceeSPaul Burton WARN_ON(core > (MIPS_GLOBALNUMBER_CORE >> MIPS_GLOBALNUMBER_CORE_SHF));
2033856fbceeSPaul Burton
2034856fbceeSPaul Burton cpuinfo->globalnumber &= ~MIPS_GLOBALNUMBER_CORE;
2035856fbceeSPaul Burton cpuinfo->globalnumber |= core << MIPS_GLOBALNUMBER_CORE_SHF;
2036856fbceeSPaul Burton }
2037856fbceeSPaul Burton
cpu_set_vpe_id(struct cpuinfo_mips * cpuinfo,unsigned int vpe)2038856fbceeSPaul Burton void cpu_set_vpe_id(struct cpuinfo_mips *cpuinfo, unsigned int vpe)
2039856fbceeSPaul Burton {
2040856fbceeSPaul Burton /* Ensure the VP(E) ID fits in the field */
2041856fbceeSPaul Burton WARN_ON(vpe > (MIPS_GLOBALNUMBER_VP >> MIPS_GLOBALNUMBER_VP_SHF));
2042856fbceeSPaul Burton
2043856fbceeSPaul Burton /* Ensure we're not using VP(E)s without support */
2044856fbceeSPaul Burton WARN_ON(vpe && !IS_ENABLED(CONFIG_MIPS_MT_SMP) &&
2045856fbceeSPaul Burton !IS_ENABLED(CONFIG_CPU_MIPSR6));
2046856fbceeSPaul Burton
2047856fbceeSPaul Burton cpuinfo->globalnumber &= ~MIPS_GLOBALNUMBER_VP;
2048856fbceeSPaul Burton cpuinfo->globalnumber |= vpe << MIPS_GLOBALNUMBER_VP_SHF;
2049856fbceeSPaul Burton }
2050