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