diff options
Diffstat (limited to 'arch/sparc/kernel/cpu.c')
-rw-r--r-- | arch/sparc/kernel/cpu.c | 413 |
1 files changed, 292 insertions, 121 deletions
diff --git a/arch/sparc/kernel/cpu.c b/arch/sparc/kernel/cpu.c index 1fc17f59c6bf..6c2da2420f76 100644 --- a/arch/sparc/kernel/cpu.c +++ b/arch/sparc/kernel/cpu.c | |||
@@ -8,6 +8,8 @@ | |||
8 | #include <linux/init.h> | 8 | #include <linux/init.h> |
9 | #include <linux/smp.h> | 9 | #include <linux/smp.h> |
10 | #include <linux/threads.h> | 10 | #include <linux/threads.h> |
11 | |||
12 | #include <asm/spitfire.h> | ||
11 | #include <asm/oplib.h> | 13 | #include <asm/oplib.h> |
12 | #include <asm/page.h> | 14 | #include <asm/page.h> |
13 | #include <asm/head.h> | 15 | #include <asm/head.h> |
@@ -15,153 +17,322 @@ | |||
15 | #include <asm/mbus.h> | 17 | #include <asm/mbus.h> |
16 | #include <asm/cpudata.h> | 18 | #include <asm/cpudata.h> |
17 | 19 | ||
20 | #include "kernel.h" | ||
21 | |||
18 | DEFINE_PER_CPU(cpuinfo_sparc, __cpu_data) = { 0 }; | 22 | DEFINE_PER_CPU(cpuinfo_sparc, __cpu_data) = { 0 }; |
19 | 23 | ||
20 | struct cpu_iu_info { | 24 | struct cpu_info { |
21 | int psr_impl; | 25 | int psr_vers; |
22 | int psr_vers; | 26 | const char *name; |
23 | char* cpu_name; /* should be enough I hope... */ | 27 | }; |
28 | |||
29 | struct fpu_info { | ||
30 | int fp_vers; | ||
31 | const char *name; | ||
24 | }; | 32 | }; |
25 | 33 | ||
26 | struct cpu_fp_info { | 34 | #define NOCPU 8 |
27 | int psr_impl; | 35 | #define NOFPU 8 |
28 | int fp_vers; | 36 | |
29 | char* fp_name; | 37 | struct manufacturer_info { |
38 | int psr_impl; | ||
39 | struct cpu_info cpu_info[NOCPU]; | ||
40 | struct fpu_info fpu_info[NOFPU]; | ||
30 | }; | 41 | }; |
31 | 42 | ||
43 | #define CPU(ver, _name) \ | ||
44 | { .psr_vers = ver, .name = _name } | ||
45 | |||
46 | #define FPU(ver, _name) \ | ||
47 | { .fp_vers = ver, .name = _name } | ||
48 | |||
49 | static const struct manufacturer_info __initconst manufacturer_info[] = { | ||
50 | { | ||
51 | 0, | ||
52 | /* Sun4/100, 4/200, SLC */ | ||
53 | .cpu_info = { | ||
54 | CPU(0, "Fujitsu MB86900/1A or LSI L64831 SparcKIT-40"), | ||
55 | /* borned STP1012PGA */ | ||
56 | CPU(4, "Fujitsu MB86904"), | ||
57 | CPU(5, "Fujitsu TurboSparc MB86907"), | ||
58 | CPU(-1, NULL) | ||
59 | }, | ||
60 | .fpu_info = { | ||
61 | FPU(0, "Fujitsu MB86910 or Weitek WTL1164/5"), | ||
62 | FPU(1, "Fujitsu MB86911 or Weitek WTL1164/5 or LSI L64831"), | ||
63 | FPU(2, "LSI Logic L64802 or Texas Instruments ACT8847"), | ||
64 | /* SparcStation SLC, SparcStation1 */ | ||
65 | FPU(3, "Weitek WTL3170/2"), | ||
66 | /* SPARCstation-5 */ | ||
67 | FPU(4, "Lsi Logic/Meiko L64804 or compatible"), | ||
68 | FPU(-1, NULL) | ||
69 | } | ||
70 | },{ | ||
71 | 1, | ||
72 | .cpu_info = { | ||
73 | /* SparcStation2, SparcServer 490 & 690 */ | ||
74 | CPU(0, "LSI Logic Corporation - L64811"), | ||
75 | /* SparcStation2 */ | ||
76 | CPU(1, "Cypress/ROSS CY7C601"), | ||
77 | /* Embedded controller */ | ||
78 | CPU(3, "Cypress/ROSS CY7C611"), | ||
79 | /* Ross Technologies HyperSparc */ | ||
80 | CPU(0xf, "ROSS HyperSparc RT620"), | ||
81 | CPU(0xe, "ROSS HyperSparc RT625 or RT626"), | ||
82 | CPU(-1, NULL) | ||
83 | }, | ||
84 | .fpu_info = { | ||
85 | FPU(0, "ROSS HyperSparc combined IU/FPU"), | ||
86 | FPU(1, "Lsi Logic L64814"), | ||
87 | FPU(2, "Texas Instruments TMS390-C602A"), | ||
88 | FPU(3, "Cypress CY7C602 FPU"), | ||
89 | FPU(-1, NULL) | ||
90 | } | ||
91 | },{ | ||
92 | 2, | ||
93 | .cpu_info = { | ||
94 | /* ECL Implementation, CRAY S-MP Supercomputer... AIEEE! */ | ||
95 | /* Someone please write the code to support this beast! ;) */ | ||
96 | CPU(0, "Bipolar Integrated Technology - B5010"), | ||
97 | CPU(-1, NULL) | ||
98 | }, | ||
99 | .fpu_info = { | ||
100 | FPU(-1, NULL) | ||
101 | } | ||
102 | },{ | ||
103 | 3, | ||
104 | .cpu_info = { | ||
105 | CPU(0, "LSI Logic Corporation - unknown-type"), | ||
106 | CPU(-1, NULL) | ||
107 | }, | ||
108 | .fpu_info = { | ||
109 | FPU(-1, NULL) | ||
110 | } | ||
111 | },{ | ||
112 | 4, | ||
113 | .cpu_info = { | ||
114 | CPU(0, "Texas Instruments, Inc. - SuperSparc-(II)"), | ||
115 | /* SparcClassic -- borned STP1010TAB-50*/ | ||
116 | CPU(1, "Texas Instruments, Inc. - MicroSparc"), | ||
117 | CPU(2, "Texas Instruments, Inc. - MicroSparc II"), | ||
118 | CPU(3, "Texas Instruments, Inc. - SuperSparc 51"), | ||
119 | CPU(4, "Texas Instruments, Inc. - SuperSparc 61"), | ||
120 | CPU(5, "Texas Instruments, Inc. - unknown"), | ||
121 | CPU(-1, NULL) | ||
122 | }, | ||
123 | .fpu_info = { | ||
124 | /* SuperSparc 50 module */ | ||
125 | FPU(0, "SuperSparc on-chip FPU"), | ||
126 | /* SparcClassic */ | ||
127 | FPU(4, "TI MicroSparc on chip FPU"), | ||
128 | FPU(-1, NULL) | ||
129 | } | ||
130 | },{ | ||
131 | 5, | ||
132 | .cpu_info = { | ||
133 | CPU(0, "Matsushita - MN10501"), | ||
134 | CPU(-1, NULL) | ||
135 | }, | ||
136 | .fpu_info = { | ||
137 | FPU(0, "Matsushita MN10501"), | ||
138 | FPU(-1, NULL) | ||
139 | } | ||
140 | },{ | ||
141 | 6, | ||
142 | .cpu_info = { | ||
143 | CPU(0, "Philips Corporation - unknown"), | ||
144 | CPU(-1, NULL) | ||
145 | }, | ||
146 | .fpu_info = { | ||
147 | FPU(-1, NULL) | ||
148 | } | ||
149 | },{ | ||
150 | 7, | ||
151 | .cpu_info = { | ||
152 | CPU(0, "Harvest VLSI Design Center, Inc. - unknown"), | ||
153 | CPU(-1, NULL) | ||
154 | }, | ||
155 | .fpu_info = { | ||
156 | FPU(-1, NULL) | ||
157 | } | ||
158 | },{ | ||
159 | 8, | ||
160 | .cpu_info = { | ||
161 | CPU(0, "Systems and Processes Engineering Corporation (SPEC)"), | ||
162 | CPU(-1, NULL) | ||
163 | }, | ||
164 | .fpu_info = { | ||
165 | FPU(-1, NULL) | ||
166 | } | ||
167 | },{ | ||
168 | 9, | ||
169 | .cpu_info = { | ||
170 | /* Gallium arsenide 200MHz, BOOOOGOOOOMIPS!!! */ | ||
171 | CPU(0, "Fujitsu or Weitek Power-UP"), | ||
172 | CPU(1, "Fujitsu or Weitek Power-UP"), | ||
173 | CPU(2, "Fujitsu or Weitek Power-UP"), | ||
174 | CPU(3, "Fujitsu or Weitek Power-UP"), | ||
175 | CPU(-1, NULL) | ||
176 | }, | ||
177 | .fpu_info = { | ||
178 | FPU(3, "Fujitsu or Weitek on-chip FPU"), | ||
179 | FPU(-1, NULL) | ||
180 | } | ||
181 | },{ | ||
182 | 0x17, | ||
183 | .cpu_info = { | ||
184 | CPU(0x10, "TI UltraSparc I (SpitFire)"), | ||
185 | CPU(0x11, "TI UltraSparc II (BlackBird)"), | ||
186 | CPU(0x12, "TI UltraSparc IIi (Sabre)"), | ||
187 | CPU(0x13, "TI UltraSparc IIe (Hummingbird)"), | ||
188 | CPU(-1, NULL) | ||
189 | }, | ||
190 | .fpu_info = { | ||
191 | FPU(0x10, "UltraSparc I integrated FPU"), | ||
192 | FPU(0x11, "UltraSparc II integrated FPU"), | ||
193 | FPU(0x12, "UltraSparc IIi integrated FPU"), | ||
194 | FPU(0x13, "UltraSparc IIe integrated FPU"), | ||
195 | FPU(-1, NULL) | ||
196 | } | ||
197 | },{ | ||
198 | 0x22, | ||
199 | .cpu_info = { | ||
200 | CPU(0x10, "TI UltraSparc I (SpitFire)"), | ||
201 | CPU(-1, NULL) | ||
202 | }, | ||
203 | .fpu_info = { | ||
204 | FPU(0x10, "UltraSparc I integrated FPU"), | ||
205 | FPU(-1, NULL) | ||
206 | } | ||
207 | },{ | ||
208 | 0x3e, | ||
209 | .cpu_info = { | ||
210 | CPU(0x14, "TI UltraSparc III (Cheetah)"), | ||
211 | CPU(0x15, "TI UltraSparc III+ (Cheetah+)"), | ||
212 | CPU(0x16, "TI UltraSparc IIIi (Jalapeno)"), | ||
213 | CPU(0x18, "TI UltraSparc IV (Jaguar)"), | ||
214 | CPU(0x19, "TI UltraSparc IV+ (Panther)"), | ||
215 | CPU(0x22, "TI UltraSparc IIIi+ (Serrano)"), | ||
216 | CPU(-1, NULL) | ||
217 | }, | ||
218 | .fpu_info = { | ||
219 | FPU(0x14, "UltraSparc III integrated FPU"), | ||
220 | FPU(0x15, "UltraSparc III+ integrated FPU"), | ||
221 | FPU(0x16, "UltraSparc IIIi integrated FPU"), | ||
222 | FPU(0x18, "UltraSparc IV integrated FPU"), | ||
223 | FPU(0x19, "UltraSparc IV+ integrated FPU"), | ||
224 | FPU(0x22, "UltraSparc IIIi+ integrated FPU"), | ||
225 | FPU(-1, NULL) | ||
226 | } | ||
227 | }}; | ||
228 | |||
32 | /* In order to get the fpu type correct, you need to take the IDPROM's | 229 | /* In order to get the fpu type correct, you need to take the IDPROM's |
33 | * machine type value into consideration too. I will fix this. | 230 | * machine type value into consideration too. I will fix this. |
34 | */ | 231 | */ |
35 | static struct cpu_fp_info linux_sparc_fpu[] = { | ||
36 | { 0, 0, "Fujitsu MB86910 or Weitek WTL1164/5"}, | ||
37 | { 0, 1, "Fujitsu MB86911 or Weitek WTL1164/5 or LSI L64831"}, | ||
38 | { 0, 2, "LSI Logic L64802 or Texas Instruments ACT8847"}, | ||
39 | /* SparcStation SLC, SparcStation1 */ | ||
40 | { 0, 3, "Weitek WTL3170/2"}, | ||
41 | /* SPARCstation-5 */ | ||
42 | { 0, 4, "Lsi Logic/Meiko L64804 or compatible"}, | ||
43 | { 0, 5, "reserved"}, | ||
44 | { 0, 6, "reserved"}, | ||
45 | { 0, 7, "No FPU"}, | ||
46 | { 1, 0, "ROSS HyperSparc combined IU/FPU"}, | ||
47 | { 1, 1, "Lsi Logic L64814"}, | ||
48 | { 1, 2, "Texas Instruments TMS390-C602A"}, | ||
49 | { 1, 3, "Cypress CY7C602 FPU"}, | ||
50 | { 1, 4, "reserved"}, | ||
51 | { 1, 5, "reserved"}, | ||
52 | { 1, 6, "reserved"}, | ||
53 | { 1, 7, "No FPU"}, | ||
54 | { 2, 0, "BIT B5010 or B5110/20 or B5210"}, | ||
55 | { 2, 1, "reserved"}, | ||
56 | { 2, 2, "reserved"}, | ||
57 | { 2, 3, "reserved"}, | ||
58 | { 2, 4, "reserved"}, | ||
59 | { 2, 5, "reserved"}, | ||
60 | { 2, 6, "reserved"}, | ||
61 | { 2, 7, "No FPU"}, | ||
62 | /* SuperSparc 50 module */ | ||
63 | { 4, 0, "SuperSparc on-chip FPU"}, | ||
64 | /* SparcClassic */ | ||
65 | { 4, 4, "TI MicroSparc on chip FPU"}, | ||
66 | { 5, 0, "Matsushita MN10501"}, | ||
67 | { 5, 1, "reserved"}, | ||
68 | { 5, 2, "reserved"}, | ||
69 | { 5, 3, "reserved"}, | ||
70 | { 5, 4, "reserved"}, | ||
71 | { 5, 5, "reserved"}, | ||
72 | { 5, 6, "reserved"}, | ||
73 | { 5, 7, "No FPU"}, | ||
74 | { 9, 3, "Fujitsu or Weitek on-chip FPU"}, | ||
75 | }; | ||
76 | 232 | ||
77 | #define NSPARCFPU ARRAY_SIZE(linux_sparc_fpu) | 233 | const char *sparc_cpu_type; |
78 | 234 | const char *sparc_fpu_type; | |
79 | static struct cpu_iu_info linux_sparc_chips[] = { | ||
80 | /* Sun4/100, 4/200, SLC */ | ||
81 | { 0, 0, "Fujitsu MB86900/1A or LSI L64831 SparcKIT-40"}, | ||
82 | /* borned STP1012PGA */ | ||
83 | { 0, 4, "Fujitsu MB86904"}, | ||
84 | { 0, 5, "Fujitsu TurboSparc MB86907"}, | ||
85 | /* SparcStation2, SparcServer 490 & 690 */ | ||
86 | { 1, 0, "LSI Logic Corporation - L64811"}, | ||
87 | /* SparcStation2 */ | ||
88 | { 1, 1, "Cypress/ROSS CY7C601"}, | ||
89 | /* Embedded controller */ | ||
90 | { 1, 3, "Cypress/ROSS CY7C611"}, | ||
91 | /* Ross Technologies HyperSparc */ | ||
92 | { 1, 0xf, "ROSS HyperSparc RT620"}, | ||
93 | { 1, 0xe, "ROSS HyperSparc RT625 or RT626"}, | ||
94 | /* ECL Implementation, CRAY S-MP Supercomputer... AIEEE! */ | ||
95 | /* Someone please write the code to support this beast! ;) */ | ||
96 | { 2, 0, "Bipolar Integrated Technology - B5010"}, | ||
97 | { 3, 0, "LSI Logic Corporation - unknown-type"}, | ||
98 | { 4, 0, "Texas Instruments, Inc. - SuperSparc-(II)"}, | ||
99 | /* SparcClassic -- borned STP1010TAB-50*/ | ||
100 | { 4, 1, "Texas Instruments, Inc. - MicroSparc"}, | ||
101 | { 4, 2, "Texas Instruments, Inc. - MicroSparc II"}, | ||
102 | { 4, 3, "Texas Instruments, Inc. - SuperSparc 51"}, | ||
103 | { 4, 4, "Texas Instruments, Inc. - SuperSparc 61"}, | ||
104 | { 4, 5, "Texas Instruments, Inc. - unknown"}, | ||
105 | { 5, 0, "Matsushita - MN10501"}, | ||
106 | { 6, 0, "Philips Corporation - unknown"}, | ||
107 | { 7, 0, "Harvest VLSI Design Center, Inc. - unknown"}, | ||
108 | /* Gallium arsenide 200MHz, BOOOOGOOOOMIPS!!! */ | ||
109 | { 8, 0, "Systems and Processes Engineering Corporation (SPEC)"}, | ||
110 | { 9, 0, "Fujitsu or Weitek Power-UP"}, | ||
111 | { 9, 1, "Fujitsu or Weitek Power-UP"}, | ||
112 | { 9, 2, "Fujitsu or Weitek Power-UP"}, | ||
113 | { 9, 3, "Fujitsu or Weitek Power-UP"}, | ||
114 | { 0xa, 0, "UNKNOWN CPU-VENDOR/TYPE"}, | ||
115 | { 0xb, 0, "UNKNOWN CPU-VENDOR/TYPE"}, | ||
116 | { 0xc, 0, "UNKNOWN CPU-VENDOR/TYPE"}, | ||
117 | { 0xd, 0, "UNKNOWN CPU-VENDOR/TYPE"}, | ||
118 | { 0xe, 0, "UNKNOWN CPU-VENDOR/TYPE"}, | ||
119 | { 0xf, 0, "UNKNOWN CPU-VENDOR/TYPE"}, | ||
120 | }; | ||
121 | 235 | ||
122 | #define NSPARCCHIPS ARRAY_SIZE(linux_sparc_chips) | 236 | unsigned int fsr_storage; |
123 | 237 | ||
124 | char *sparc_cpu_type; | 238 | static void set_cpu_and_fpu(int psr_impl, int psr_vers, int fpu_vers) |
125 | char *sparc_fpu_type; | 239 | { |
240 | sparc_cpu_type = NULL; | ||
241 | sparc_fpu_type = NULL; | ||
242 | if (psr_impl < ARRAY_SIZE(manufacturer_info)) | ||
243 | { | ||
244 | const struct cpu_info *cpu; | ||
245 | const struct fpu_info *fpu; | ||
126 | 246 | ||
127 | unsigned int fsr_storage; | 247 | cpu = &manufacturer_info[psr_impl].cpu_info[0]; |
248 | while (cpu->psr_vers != -1) | ||
249 | { | ||
250 | if (cpu->psr_vers == psr_vers) { | ||
251 | sparc_cpu_type = cpu->name; | ||
252 | sparc_fpu_type = "No FPU"; | ||
253 | break; | ||
254 | } | ||
255 | cpu++; | ||
256 | } | ||
257 | fpu = &manufacturer_info[psr_impl].fpu_info[0]; | ||
258 | while (fpu->fp_vers != -1) | ||
259 | { | ||
260 | if (fpu->fp_vers == fpu_vers) { | ||
261 | sparc_fpu_type = fpu->name; | ||
262 | break; | ||
263 | } | ||
264 | fpu++; | ||
265 | } | ||
266 | } | ||
267 | if (sparc_cpu_type == NULL) | ||
268 | { | ||
269 | printk(KERN_ERR "CPU: Unknown chip, impl[0x%x] vers[0x%x]\n", | ||
270 | psr_impl, psr_vers); | ||
271 | sparc_cpu_type = "Unknown CPU"; | ||
272 | } | ||
273 | if (sparc_fpu_type == NULL) | ||
274 | { | ||
275 | printk(KERN_ERR "FPU: Unknown chip, impl[0x%x] vers[0x%x]\n", | ||
276 | psr_impl, fpu_vers); | ||
277 | sparc_fpu_type = "Unknown FPU"; | ||
278 | } | ||
279 | } | ||
128 | 280 | ||
281 | #ifdef CONFIG_SPARC32 | ||
129 | void __cpuinit cpu_probe(void) | 282 | void __cpuinit cpu_probe(void) |
130 | { | 283 | { |
131 | int psr_impl, psr_vers, fpu_vers; | 284 | int psr_impl, psr_vers, fpu_vers; |
132 | int i, psr; | 285 | int psr; |
133 | 286 | ||
134 | psr_impl = ((get_psr()>>28)&0xf); | 287 | psr_impl = ((get_psr() >> 28) & 0xf); |
135 | psr_vers = ((get_psr()>>24)&0xf); | 288 | psr_vers = ((get_psr() >> 24) & 0xf); |
136 | 289 | ||
137 | psr = get_psr(); | 290 | psr = get_psr(); |
138 | put_psr(psr | PSR_EF); | 291 | put_psr(psr | PSR_EF); |
139 | fpu_vers = ((get_fsr()>>17)&0x7); | 292 | fpu_vers = ((get_fsr() >> 17) & 0x7); |
140 | put_psr(psr); | 293 | put_psr(psr); |
141 | 294 | ||
142 | for(i = 0; i<NSPARCCHIPS; i++) { | 295 | set_cpu_and_fpu(psr_impl, psr_vers, fpu_vers); |
143 | if(linux_sparc_chips[i].psr_impl == psr_impl) | 296 | } |
144 | if(linux_sparc_chips[i].psr_vers == psr_vers) { | 297 | #else |
145 | sparc_cpu_type = linux_sparc_chips[i].cpu_name; | 298 | static void __init sun4v_cpu_probe(void) |
146 | break; | 299 | { |
147 | } | 300 | switch (sun4v_chip_type) { |
148 | } | 301 | case SUN4V_CHIP_NIAGARA1: |
302 | sparc_cpu_type = "UltraSparc T1 (Niagara)"; | ||
303 | sparc_fpu_type = "UltraSparc T1 integrated FPU"; | ||
304 | break; | ||
149 | 305 | ||
150 | if(i==NSPARCCHIPS) | 306 | case SUN4V_CHIP_NIAGARA2: |
151 | printk("DEBUG: psr.impl = 0x%x psr.vers = 0x%x\n", psr_impl, | 307 | sparc_cpu_type = "UltraSparc T2 (Niagara2)"; |
152 | psr_vers); | 308 | sparc_fpu_type = "UltraSparc T2 integrated FPU"; |
309 | break; | ||
153 | 310 | ||
154 | for(i = 0; i<NSPARCFPU; i++) { | 311 | default: |
155 | if(linux_sparc_fpu[i].psr_impl == psr_impl) | 312 | printk(KERN_WARNING "CPU: Unknown sun4v cpu type [%s]\n", |
156 | if(linux_sparc_fpu[i].fp_vers == fpu_vers) { | 313 | prom_cpu_compatible); |
157 | sparc_fpu_type = linux_sparc_fpu[i].fp_name; | 314 | sparc_cpu_type = "Unknown SUN4V CPU"; |
158 | break; | 315 | sparc_fpu_type = "Unknown SUN4V FPU"; |
159 | } | 316 | break; |
160 | } | 317 | } |
318 | } | ||
319 | |||
320 | static int __init cpu_type_probe(void) | ||
321 | { | ||
322 | if (tlb_type == hypervisor) { | ||
323 | sun4v_cpu_probe(); | ||
324 | } else { | ||
325 | unsigned long ver; | ||
326 | int manuf, impl; | ||
161 | 327 | ||
162 | if(i == NSPARCFPU) { | 328 | __asm__ __volatile__("rdpr %%ver, %0" : "=r" (ver)); |
163 | printk("DEBUG: psr.impl = 0x%x fsr.vers = 0x%x\n", psr_impl, | 329 | |
164 | fpu_vers); | 330 | manuf = ((ver >> 48) & 0xffff); |
165 | sparc_fpu_type = linux_sparc_fpu[31].fp_name; | 331 | impl = ((ver >> 32) & 0xffff); |
332 | set_cpu_and_fpu(manuf, impl, impl); | ||
166 | } | 333 | } |
334 | return 0; | ||
167 | } | 335 | } |
336 | |||
337 | arch_initcall(cpu_type_probe); | ||
338 | #endif | ||