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