Merge branch 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/linux-arm-soc
[pandora-kernel.git] / arch / sparc / kernel / cpu.c
1 /* cpu.c: Dinky routines to look for the kind of Sparc cpu
2  *        we are on.
3  *
4  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
5  */
6
7 #include <linux/seq_file.h>
8 #include <linux/kernel.h>
9 #include <linux/module.h>
10 #include <linux/init.h>
11 #include <linux/smp.h>
12 #include <linux/threads.h>
13
14 #include <asm/spitfire.h>
15 #include <asm/pgtable.h>
16 #include <asm/oplib.h>
17 #include <asm/setup.h>
18 #include <asm/page.h>
19 #include <asm/head.h>
20 #include <asm/psr.h>
21 #include <asm/mbus.h>
22 #include <asm/cpudata.h>
23
24 #include "kernel.h"
25
26 DEFINE_PER_CPU(cpuinfo_sparc, __cpu_data) = { 0 };
27 EXPORT_PER_CPU_SYMBOL(__cpu_data);
28
29 int ncpus_probed;
30 unsigned int fsr_storage;
31
32 struct cpu_info {
33         int psr_vers;
34         const char *name;
35         const char *pmu_name;
36 };
37
38 struct fpu_info {
39         int fp_vers;
40         const char *name;
41 };
42
43 #define NOCPU 8
44 #define NOFPU 8
45
46 struct manufacturer_info {
47         int psr_impl;
48         struct cpu_info cpu_info[NOCPU];
49         struct fpu_info fpu_info[NOFPU];
50 };
51
52 #define CPU(ver, _name) \
53 { .psr_vers = ver, .name = _name }
54
55 #define CPU_PMU(ver, _name, _pmu_name)  \
56 { .psr_vers = ver, .name = _name, .pmu_name = _pmu_name }
57
58 #define FPU(ver, _name) \
59 { .fp_vers = ver, .name = _name }
60
61 static const struct manufacturer_info __initconst manufacturer_info[] = {
62 {
63         0,
64         /* Sun4/100, 4/200, SLC */
65         .cpu_info = {
66                 CPU(0, "Fujitsu  MB86900/1A or LSI L64831 SparcKIT-40"),
67                 /* borned STP1012PGA */
68                 CPU(4,  "Fujitsu  MB86904"),
69                 CPU(5, "Fujitsu TurboSparc MB86907"),
70                 CPU(-1, NULL)
71         },
72         .fpu_info = {
73                 FPU(0, "Fujitsu MB86910 or Weitek WTL1164/5"),
74                 FPU(1, "Fujitsu MB86911 or Weitek WTL1164/5 or LSI L64831"),
75                 FPU(2, "LSI Logic L64802 or Texas Instruments ACT8847"),
76                 /* SparcStation SLC, SparcStation1 */
77                 FPU(3, "Weitek WTL3170/2"),
78                 /* SPARCstation-5 */
79                 FPU(4, "Lsi Logic/Meiko L64804 or compatible"),
80                 FPU(-1, NULL)
81         }
82 },{
83         1,
84         .cpu_info = {
85                 /* SparcStation2, SparcServer 490 & 690 */
86                 CPU(0, "LSI Logic Corporation - L64811"),
87                 /* SparcStation2 */
88                 CPU(1, "Cypress/ROSS CY7C601"),
89                 /* Embedded controller */
90                 CPU(3, "Cypress/ROSS CY7C611"),
91                 /* Ross Technologies HyperSparc */
92                 CPU(0xf, "ROSS HyperSparc RT620"),
93                 CPU(0xe, "ROSS HyperSparc RT625 or RT626"),
94                 CPU(-1, NULL)
95         },
96         .fpu_info = {
97                 FPU(0, "ROSS HyperSparc combined IU/FPU"),
98                 FPU(1, "Lsi Logic L64814"),
99                 FPU(2, "Texas Instruments TMS390-C602A"),
100                 FPU(3, "Cypress CY7C602 FPU"),
101                 FPU(-1, NULL)
102         }
103 },{
104         2,
105         .cpu_info = {
106                 /* ECL Implementation, CRAY S-MP Supercomputer... AIEEE! */
107                 /* Someone please write the code to support this beast! ;) */
108                 CPU(0, "Bipolar Integrated Technology - B5010"),
109                 CPU(-1, NULL)
110         },
111         .fpu_info = {
112                 FPU(-1, NULL)
113         }
114 },{
115         3,
116         .cpu_info = {
117                 CPU(0, "LSI Logic Corporation - unknown-type"),
118                 CPU(-1, NULL)
119         },
120         .fpu_info = {
121                 FPU(-1, NULL)
122         }
123 },{
124         4,
125         .cpu_info = {
126                 CPU(0, "Texas Instruments, Inc. - SuperSparc-(II)"),
127                 /* SparcClassic  --  borned STP1010TAB-50*/
128                 CPU(1, "Texas Instruments, Inc. - MicroSparc"),
129                 CPU(2, "Texas Instruments, Inc. - MicroSparc II"),
130                 CPU(3, "Texas Instruments, Inc. - SuperSparc 51"),
131                 CPU(4, "Texas Instruments, Inc. - SuperSparc 61"),
132                 CPU(5, "Texas Instruments, Inc. - unknown"),
133                 CPU(-1, NULL)
134         },
135         .fpu_info = {
136                 /* SuperSparc 50 module */
137                 FPU(0, "SuperSparc on-chip FPU"),
138                 /* SparcClassic */
139                 FPU(4, "TI MicroSparc on chip FPU"),
140                 FPU(-1, NULL)
141         }
142 },{
143         5,
144         .cpu_info = {
145                 CPU(0, "Matsushita - MN10501"),
146                 CPU(-1, NULL)
147         },
148         .fpu_info = {
149                 FPU(0, "Matsushita MN10501"),
150                 FPU(-1, NULL)
151         }
152 },{
153         6,
154         .cpu_info = {
155                 CPU(0, "Philips Corporation - unknown"),
156                 CPU(-1, NULL)
157         },
158         .fpu_info = {
159                 FPU(-1, NULL)
160         }
161 },{
162         7,
163         .cpu_info = {
164                 CPU(0, "Harvest VLSI Design Center, Inc. - unknown"),
165                 CPU(-1, NULL)
166         },
167         .fpu_info = {
168                 FPU(-1, NULL)
169         }
170 },{
171         8,
172         .cpu_info = {
173                 CPU(0, "Systems and Processes Engineering Corporation (SPEC)"),
174                 CPU(-1, NULL)
175         },
176         .fpu_info = {
177                 FPU(-1, NULL)
178         }
179 },{
180         9,
181         .cpu_info = {
182                 /* Gallium arsenide 200MHz, BOOOOGOOOOMIPS!!! */
183                 CPU(0, "Fujitsu or Weitek Power-UP"),
184                 CPU(1, "Fujitsu or Weitek Power-UP"),
185                 CPU(2, "Fujitsu or Weitek Power-UP"),
186                 CPU(3, "Fujitsu or Weitek Power-UP"),
187                 CPU(-1, NULL)
188         },
189         .fpu_info = {
190                 FPU(3, "Fujitsu or Weitek on-chip FPU"),
191                 FPU(-1, NULL)
192         }
193 },{
194         0xF,            /* Aeroflex Gaisler */
195         .cpu_info = {
196                 CPU(3, "LEON"),
197                 CPU(-1, NULL)
198         },
199         .fpu_info = {
200                 FPU(2, "GRFPU"),
201                 FPU(3, "GRFPU-Lite"),
202                 FPU(-1, NULL)
203         }
204 },{
205         0x17,
206         .cpu_info = {
207                 CPU_PMU(0x10, "TI UltraSparc I   (SpitFire)", "ultra12"),
208                 CPU_PMU(0x11, "TI UltraSparc II  (BlackBird)", "ultra12"),
209                 CPU_PMU(0x12, "TI UltraSparc IIi (Sabre)", "ultra12"),
210                 CPU_PMU(0x13, "TI UltraSparc IIe (Hummingbird)", "ultra12"),
211                 CPU(-1, NULL)
212         },
213         .fpu_info = {
214                 FPU(0x10, "UltraSparc I integrated FPU"),
215                 FPU(0x11, "UltraSparc II integrated FPU"),
216                 FPU(0x12, "UltraSparc IIi integrated FPU"),
217                 FPU(0x13, "UltraSparc IIe integrated FPU"),
218                 FPU(-1, NULL)
219         }
220 },{
221         0x22,
222         .cpu_info = {
223                 CPU_PMU(0x10, "TI UltraSparc I   (SpitFire)", "ultra12"),
224                 CPU(-1, NULL)
225         },
226         .fpu_info = {
227                 FPU(0x10, "UltraSparc I integrated FPU"),
228                 FPU(-1, NULL)
229         }
230 },{
231         0x3e,
232         .cpu_info = {
233                 CPU_PMU(0x14, "TI UltraSparc III (Cheetah)", "ultra3"),
234                 CPU_PMU(0x15, "TI UltraSparc III+ (Cheetah+)", "ultra3+"),
235                 CPU_PMU(0x16, "TI UltraSparc IIIi (Jalapeno)", "ultra3i"),
236                 CPU_PMU(0x18, "TI UltraSparc IV (Jaguar)", "ultra3+"),
237                 CPU_PMU(0x19, "TI UltraSparc IV+ (Panther)", "ultra4+"),
238                 CPU_PMU(0x22, "TI UltraSparc IIIi+ (Serrano)", "ultra3i"),
239                 CPU(-1, NULL)
240         },
241         .fpu_info = {
242                 FPU(0x14, "UltraSparc III integrated FPU"),
243                 FPU(0x15, "UltraSparc III+ integrated FPU"),
244                 FPU(0x16, "UltraSparc IIIi integrated FPU"),
245                 FPU(0x18, "UltraSparc IV integrated FPU"),
246                 FPU(0x19, "UltraSparc IV+ integrated FPU"),
247                 FPU(0x22, "UltraSparc IIIi+ integrated FPU"),
248                 FPU(-1, NULL)
249         }
250 }};
251
252 /* In order to get the fpu type correct, you need to take the IDPROM's
253  * machine type value into consideration too.  I will fix this.
254  */
255
256 static const char *sparc_cpu_type;
257 static const char *sparc_fpu_type;
258 const char *sparc_pmu_type;
259
260
261 static void __init set_cpu_and_fpu(int psr_impl, int psr_vers, int fpu_vers)
262 {
263         const struct manufacturer_info *manuf;
264         int i;
265
266         sparc_cpu_type = NULL;
267         sparc_fpu_type = NULL;
268         sparc_pmu_type = NULL;
269         manuf = NULL;
270
271         for (i = 0; i < ARRAY_SIZE(manufacturer_info); i++)
272         {
273                 if (psr_impl == manufacturer_info[i].psr_impl) {
274                         manuf = &manufacturer_info[i];
275                         break;
276                 }
277         }
278         if (manuf != NULL)
279         {
280                 const struct cpu_info *cpu;
281                 const struct fpu_info *fpu;
282
283                 cpu = &manuf->cpu_info[0];
284                 while (cpu->psr_vers != -1)
285                 {
286                         if (cpu->psr_vers == psr_vers) {
287                                 sparc_cpu_type = cpu->name;
288                                 sparc_pmu_type = cpu->pmu_name;
289                                 sparc_fpu_type = "No FPU";
290                                 break;
291                         }
292                         cpu++;
293                 }
294                 fpu =  &manuf->fpu_info[0];
295                 while (fpu->fp_vers != -1)
296                 {
297                         if (fpu->fp_vers == fpu_vers) {
298                                 sparc_fpu_type = fpu->name;
299                                 break;
300                         }
301                         fpu++;
302                 }
303         }
304         if (sparc_cpu_type == NULL)
305         {
306                 printk(KERN_ERR "CPU: Unknown chip, impl[0x%x] vers[0x%x]\n",
307                        psr_impl, psr_vers);
308                 sparc_cpu_type = "Unknown CPU";
309         }
310         if (sparc_fpu_type == NULL)
311         {
312                 printk(KERN_ERR "FPU: Unknown chip, impl[0x%x] vers[0x%x]\n",
313                        psr_impl, fpu_vers);
314                 sparc_fpu_type = "Unknown FPU";
315         }
316         if (sparc_pmu_type == NULL)
317                 sparc_pmu_type = "Unknown PMU";
318 }
319
320 #ifdef CONFIG_SPARC32
321 static int show_cpuinfo(struct seq_file *m, void *__unused)
322 {
323         seq_printf(m,
324                    "cpu\t\t: %s\n"
325                    "fpu\t\t: %s\n"
326                    "promlib\t\t: Version %d Revision %d\n"
327                    "prom\t\t: %d.%d\n"
328                    "type\t\t: %s\n"
329                    "ncpus probed\t: %d\n"
330                    "ncpus active\t: %d\n"
331 #ifndef CONFIG_SMP
332                    "CPU0Bogo\t: %lu.%02lu\n"
333                    "CPU0ClkTck\t: %ld\n"
334 #endif
335                    ,
336                    sparc_cpu_type,
337                    sparc_fpu_type ,
338                    romvec->pv_romvers,
339                    prom_rev,
340                    romvec->pv_printrev >> 16,
341                    romvec->pv_printrev & 0xffff,
342                    &cputypval[0],
343                    ncpus_probed,
344                    num_online_cpus()
345 #ifndef CONFIG_SMP
346                    , cpu_data(0).udelay_val/(500000/HZ),
347                    (cpu_data(0).udelay_val/(5000/HZ)) % 100,
348                    cpu_data(0).clock_tick
349 #endif
350                 );
351
352 #ifdef CONFIG_SMP
353         smp_bogo(m);
354 #endif
355         mmu_info(m);
356 #ifdef CONFIG_SMP
357         smp_info(m);
358 #endif
359         return 0;
360 }
361 #endif /* CONFIG_SPARC32 */
362
363 #ifdef CONFIG_SPARC64
364 unsigned int dcache_parity_tl1_occurred;
365 unsigned int icache_parity_tl1_occurred;
366
367
368 static int show_cpuinfo(struct seq_file *m, void *__unused)
369 {
370         seq_printf(m,
371                    "cpu\t\t: %s\n"
372                    "fpu\t\t: %s\n"
373                    "pmu\t\t: %s\n"
374                    "prom\t\t: %s\n"
375                    "type\t\t: %s\n"
376                    "ncpus probed\t: %d\n"
377                    "ncpus active\t: %d\n"
378                    "D$ parity tl1\t: %u\n"
379                    "I$ parity tl1\t: %u\n"
380 #ifndef CONFIG_SMP
381                    "Cpu0ClkTck\t: %016lx\n"
382 #endif
383                    ,
384                    sparc_cpu_type,
385                    sparc_fpu_type,
386                    sparc_pmu_type,
387                    prom_version,
388                    ((tlb_type == hypervisor) ?
389                     "sun4v" :
390                     "sun4u"),
391                    ncpus_probed,
392                    num_online_cpus(),
393                    dcache_parity_tl1_occurred,
394                    icache_parity_tl1_occurred
395 #ifndef CONFIG_SMP
396                    , cpu_data(0).clock_tick
397 #endif
398                 );
399 #ifdef CONFIG_SMP
400         smp_bogo(m);
401 #endif
402         mmu_info(m);
403 #ifdef CONFIG_SMP
404         smp_info(m);
405 #endif
406         return 0;
407 }
408 #endif /* CONFIG_SPARC64 */
409
410 static void *c_start(struct seq_file *m, loff_t *pos)
411 {
412         /* The pointer we are returning is arbitrary,
413          * it just has to be non-NULL and not IS_ERR
414          * in the success case.
415          */
416         return *pos == 0 ? &c_start : NULL;
417 }
418
419 static void *c_next(struct seq_file *m, void *v, loff_t *pos)
420 {
421         ++*pos;
422         return c_start(m, pos);
423 }
424
425 static void c_stop(struct seq_file *m, void *v)
426 {
427 }
428
429 const struct seq_operations cpuinfo_op = {
430         .start =c_start,
431         .next = c_next,
432         .stop = c_stop,
433         .show = show_cpuinfo,
434 };
435
436 #ifdef CONFIG_SPARC32
437 static int __init cpu_type_probe(void)
438 {
439         int psr_impl, psr_vers, fpu_vers;
440         int psr;
441
442         psr_impl = ((get_psr() >> 28) & 0xf);
443         psr_vers = ((get_psr() >> 24) & 0xf);
444
445         psr = get_psr();
446         put_psr(psr | PSR_EF);
447 #ifdef CONFIG_SPARC_LEON
448         fpu_vers = get_psr() & PSR_EF ? ((get_fsr() >> 17) & 0x7) : 7;
449 #else
450         fpu_vers = ((get_fsr() >> 17) & 0x7);
451 #endif
452
453         put_psr(psr);
454
455         set_cpu_and_fpu(psr_impl, psr_vers, fpu_vers);
456
457         return 0;
458 }
459 #endif /* CONFIG_SPARC32 */
460
461 #ifdef CONFIG_SPARC64
462 static void __init sun4v_cpu_probe(void)
463 {
464         switch (sun4v_chip_type) {
465         case SUN4V_CHIP_NIAGARA1:
466                 sparc_cpu_type = "UltraSparc T1 (Niagara)";
467                 sparc_fpu_type = "UltraSparc T1 integrated FPU";
468                 sparc_pmu_type = "niagara";
469                 break;
470
471         case SUN4V_CHIP_NIAGARA2:
472                 sparc_cpu_type = "UltraSparc T2 (Niagara2)";
473                 sparc_fpu_type = "UltraSparc T2 integrated FPU";
474                 sparc_pmu_type = "niagara2";
475                 break;
476
477         case SUN4V_CHIP_NIAGARA3:
478                 sparc_cpu_type = "UltraSparc T3 (Niagara3)";
479                 sparc_fpu_type = "UltraSparc T3 integrated FPU";
480                 sparc_pmu_type = "niagara3";
481                 break;
482
483         default:
484                 printk(KERN_WARNING "CPU: Unknown sun4v cpu type [%s]\n",
485                        prom_cpu_compatible);
486                 sparc_cpu_type = "Unknown SUN4V CPU";
487                 sparc_fpu_type = "Unknown SUN4V FPU";
488                 sparc_pmu_type = "Unknown SUN4V PMU";
489                 break;
490         }
491 }
492
493 static int __init cpu_type_probe(void)
494 {
495         if (tlb_type == hypervisor) {
496                 sun4v_cpu_probe();
497         } else {
498                 unsigned long ver;
499                 int manuf, impl;
500
501                 __asm__ __volatile__("rdpr %%ver, %0" : "=r" (ver));
502
503                 manuf = ((ver >> 48) & 0xffff);
504                 impl = ((ver >> 32) & 0xffff);
505                 set_cpu_and_fpu(manuf, impl, impl);
506         }
507         return 0;
508 }
509 #endif /* CONFIG_SPARC64 */
510
511 early_initcall(cpu_type_probe);