cpu-probe.c 16.1 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1
2
3
4
/*
 * Processor capabilities determination functions.
 *
 * Copyright (C) xxxx  the Anonymous
5
 * Copyright (C) 2003, 2004  Maciej W. Rozycki
Linus Torvalds's avatar
Linus Torvalds committed
6
 * Copyright (C) 1994 - 2003 Ralf Baechle
7
 * Copyright (C) 2001, 2004  MIPS Inc.
Linus Torvalds's avatar
Linus Torvalds committed
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version
 * 2 of the License, or (at your option) any later version.
 */
#include <linux/config.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/ptrace.h>
#include <linux/stddef.h>

#include <asm/cpu.h>
#include <asm/fpu.h>
#include <asm/mipsregs.h>
#include <asm/system.h>

/*
 * Not all of the MIPS CPUs have the "wait" instruction available. Moreover,
 * the implementation of the "wait" feature differs between CPU families. This
 * points to the function that implements CPU specific wait.
 * The wait instruction stops the pipeline and reduces the power consumption of
 * the CPU very much.
 */
void (*cpu_wait)(void) = NULL;

static void r3081_wait(void)
{
	unsigned long cfg = read_c0_conf();
	write_c0_conf(cfg | R30XX_CONF_HALT);
}

static void r39xx_wait(void)
{
	unsigned long cfg = read_c0_conf();
	write_c0_conf(cfg | TX39_CONF_HALT);
}

static void r4k_wait(void)
{
	__asm__(".set\tmips3\n\t"
		"wait\n\t"
		".set\tmips0");
}

53
54
/* The Au1xxx wait is available only if using 32khz counter or
 * external timer source, but specifically not CP0 Counter. */
55
int allow_au1k_wait;
56

57
static void au1k_wait(void)
Linus Torvalds's avatar
Linus Torvalds committed
58
59
{
	/* using the wait instruction makes CP0 counter unusable */
60
61
62
	__asm__(".set mips3\n\t"
		"cache 0x14, 0(%0)\n\t"
		"cache 0x14, 32(%0)\n\t"
63
64
		"sync\n\t"
		"nop\n\t"
Linus Torvalds's avatar
Linus Torvalds committed
65
66
67
68
69
		"wait\n\t"
		"nop\n\t"
		"nop\n\t"
		"nop\n\t"
		"nop\n\t"
70
		".set mips0\n\t"
71
		: : "r" (au1k_wait));
Linus Torvalds's avatar
Linus Torvalds committed
72
73
}

74
75
76
77
78
79
80
81
82
83
84
static int __initdata nowait = 0;

int __init wait_disable(char *s)
{
	nowait = 1;

	return 1;
}

__setup("nowait", wait_disable);

Linus Torvalds's avatar
Linus Torvalds committed
85
86
87
88
89
static inline void check_wait(void)
{
	struct cpuinfo_mips *c = &current_cpu_data;

	printk("Checking for 'wait' instruction... ");
90
91
92
93
94
	if (nowait) {
		printk (" disabled.\n");
		return;
	}

Linus Torvalds's avatar
Linus Torvalds committed
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
	switch (c->cputype) {
	case CPU_R3081:
	case CPU_R3081E:
		cpu_wait = r3081_wait;
		printk(" available.\n");
		break;
	case CPU_TX3927:
		cpu_wait = r39xx_wait;
		printk(" available.\n");
		break;
	case CPU_R4200:
/*	case CPU_R4300: */
	case CPU_R4600:
	case CPU_R4640:
	case CPU_R4650:
	case CPU_R4700:
	case CPU_R5000:
	case CPU_NEVADA:
	case CPU_RM7000:
	case CPU_RM9000:
	case CPU_TX49XX:
	case CPU_4KC:
	case CPU_4KEC:
	case CPU_4KSC:
	case CPU_5KC:
/*	case CPU_20KC:*/
	case CPU_24K:
	case CPU_25KF:
Ralf Baechle's avatar
Ralf Baechle committed
123
	case CPU_34K:
124
 	case CPU_PR4450:
Linus Torvalds's avatar
Linus Torvalds committed
125
126
127
128
129
130
		cpu_wait = r4k_wait;
		printk(" available.\n");
		break;
	case CPU_AU1000:
	case CPU_AU1100:
	case CPU_AU1500:
Pete Popov's avatar
Pete Popov committed
131
132
	case CPU_AU1550:
	case CPU_AU1200:
133
134
135
136
137
		if (allow_au1k_wait) {
			cpu_wait = au1k_wait;
			printk(" available.\n");
		} else
			printk(" unavailable.\n");
Linus Torvalds's avatar
Linus Torvalds committed
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
		break;
	default:
		printk(" unavailable.\n");
		break;
	}
}

void __init check_bugs32(void)
{
	check_wait();
}

/*
 * Probe whether cpu has config register by trying to play with
 * alternate cache bit and see whether it matters.
 * It's used by cpu_probe to distinguish between R3000A and R3081.
 */
static inline int cpu_has_confreg(void)
{
#ifdef CONFIG_CPU_R3000
	extern unsigned long r3k_cache_size(unsigned long);
	unsigned long size1, size2;
	unsigned long cfg = read_c0_conf();

	size1 = r3k_cache_size(ST0_ISC);
	write_c0_conf(cfg ^ R30XX_CONF_AC);
	size2 = r3k_cache_size(ST0_ISC);
	write_c0_conf(cfg);
	return size1 != size2;
#else
	return 0;
#endif
}

/*
 * Get the FPU Implementation/Revision.
 */
static inline unsigned long cpu_get_fpu_id(void)
{
	unsigned long tmp, fpu_id;

	tmp = read_c0_status();
	__enable_fpu();
	fpu_id = read_32bit_cp1_register(CP1_REVISION);
	write_c0_status(tmp);
	return fpu_id;
}

/*
 * Check the CPU has an FPU the official way.
 */
static inline int __cpu_has_fpu(void)
{
	return ((cpu_get_fpu_id() & 0xff00) != FPIR_IMP_NONE);
}

194
#define R4K_OPTS (MIPS_CPU_TLB | MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE \
Linus Torvalds's avatar
Linus Torvalds committed
195
196
197
198
199
200
201
202
		| MIPS_CPU_COUNTER)

static inline void cpu_probe_legacy(struct cpuinfo_mips *c)
{
	switch (c->processor_id & 0xff00) {
	case PRID_IMP_R2000:
		c->cputype = CPU_R2000;
		c->isa_level = MIPS_CPU_ISA_I;
203
204
		c->options = MIPS_CPU_TLB | MIPS_CPU_3K_CACHE |
		             MIPS_CPU_NOFPUEX;
Linus Torvalds's avatar
Linus Torvalds committed
205
206
207
208
209
210
211
212
213
214
215
216
217
		if (__cpu_has_fpu())
			c->options |= MIPS_CPU_FPU;
		c->tlbsize = 64;
		break;
	case PRID_IMP_R3000:
		if ((c->processor_id & 0xff) == PRID_REV_R3000A)
			if (cpu_has_confreg())
				c->cputype = CPU_R3081E;
			else
				c->cputype = CPU_R3000A;
		else
			c->cputype = CPU_R3000;
		c->isa_level = MIPS_CPU_ISA_I;
218
219
		c->options = MIPS_CPU_TLB | MIPS_CPU_3K_CACHE |
		             MIPS_CPU_NOFPUEX;
Linus Torvalds's avatar
Linus Torvalds committed
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
		if (__cpu_has_fpu())
			c->options |= MIPS_CPU_FPU;
		c->tlbsize = 64;
		break;
	case PRID_IMP_R4000:
		if (read_c0_config() & CONF_SC) {
			if ((c->processor_id & 0xff) >= PRID_REV_R4400)
				c->cputype = CPU_R4400PC;
			else
				c->cputype = CPU_R4000PC;
		} else {
			if ((c->processor_id & 0xff) >= PRID_REV_R4400)
				c->cputype = CPU_R4400SC;
			else
				c->cputype = CPU_R4000SC;
		}

		c->isa_level = MIPS_CPU_ISA_III;
		c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
		             MIPS_CPU_WATCH | MIPS_CPU_VCE |
		             MIPS_CPU_LLSC;
		c->tlbsize = 48;
		break;
	case PRID_IMP_VR41XX:
		switch (c->processor_id & 0xf0) {
		case PRID_REV_VR4111:
			c->cputype = CPU_VR4111;
			break;
		case PRID_REV_VR4121:
			c->cputype = CPU_VR4121;
			break;
		case PRID_REV_VR4122:
			if ((c->processor_id & 0xf) < 0x3)
				c->cputype = CPU_VR4122;
			else
				c->cputype = CPU_VR4181A;
			break;
		case PRID_REV_VR4130:
			if ((c->processor_id & 0xf) < 0x4)
				c->cputype = CPU_VR4131;
			else
				c->cputype = CPU_VR4133;
			break;
		default:
			printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n");
			c->cputype = CPU_VR41XX;
			break;
		}
		c->isa_level = MIPS_CPU_ISA_III;
		c->options = R4K_OPTS;
		c->tlbsize = 32;
		break;
	case PRID_IMP_R4300:
		c->cputype = CPU_R4300;
		c->isa_level = MIPS_CPU_ISA_III;
		c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
		             MIPS_CPU_LLSC;
		c->tlbsize = 32;
		break;
	case PRID_IMP_R4600:
		c->cputype = CPU_R4600;
		c->isa_level = MIPS_CPU_ISA_III;
Thiemo Seufer's avatar
Thiemo Seufer committed
282
283
		c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
			     MIPS_CPU_LLSC;
Linus Torvalds's avatar
Linus Torvalds committed
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
		c->tlbsize = 48;
		break;
	#if 0
 	case PRID_IMP_R4650:
		/*
		 * This processor doesn't have an MMU, so it's not
		 * "real easy" to run Linux on it. It is left purely
		 * for documentation.  Commented out because it shares
		 * it's c0_prid id number with the TX3900.
		 */
 		c->cputype = CPU_R4650;
	 	c->isa_level = MIPS_CPU_ISA_III;
		c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_LLSC;
	        c->tlbsize = 48;
		break;
	#endif
	case PRID_IMP_TX39:
		c->isa_level = MIPS_CPU_ISA_I;
302
		c->options = MIPS_CPU_TLB | MIPS_CPU_TX39_CACHE;
Linus Torvalds's avatar
Linus Torvalds committed
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419

		if ((c->processor_id & 0xf0) == (PRID_REV_TX3927 & 0xf0)) {
			c->cputype = CPU_TX3927;
			c->tlbsize = 64;
		} else {
			switch (c->processor_id & 0xff) {
			case PRID_REV_TX3912:
				c->cputype = CPU_TX3912;
				c->tlbsize = 32;
				break;
			case PRID_REV_TX3922:
				c->cputype = CPU_TX3922;
				c->tlbsize = 64;
				break;
			default:
				c->cputype = CPU_UNKNOWN;
				break;
			}
		}
		break;
	case PRID_IMP_R4700:
		c->cputype = CPU_R4700;
		c->isa_level = MIPS_CPU_ISA_III;
		c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
		             MIPS_CPU_LLSC;
		c->tlbsize = 48;
		break;
	case PRID_IMP_TX49:
		c->cputype = CPU_TX49XX;
		c->isa_level = MIPS_CPU_ISA_III;
		c->options = R4K_OPTS | MIPS_CPU_LLSC;
		if (!(c->processor_id & 0x08))
			c->options |= MIPS_CPU_FPU | MIPS_CPU_32FPR;
		c->tlbsize = 48;
		break;
	case PRID_IMP_R5000:
		c->cputype = CPU_R5000;
		c->isa_level = MIPS_CPU_ISA_IV;
		c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
		             MIPS_CPU_LLSC;
		c->tlbsize = 48;
		break;
	case PRID_IMP_R5432:
		c->cputype = CPU_R5432;
		c->isa_level = MIPS_CPU_ISA_IV;
		c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
		             MIPS_CPU_WATCH | MIPS_CPU_LLSC;
		c->tlbsize = 48;
		break;
	case PRID_IMP_R5500:
		c->cputype = CPU_R5500;
		c->isa_level = MIPS_CPU_ISA_IV;
		c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
		             MIPS_CPU_WATCH | MIPS_CPU_LLSC;
		c->tlbsize = 48;
		break;
	case PRID_IMP_NEVADA:
		c->cputype = CPU_NEVADA;
		c->isa_level = MIPS_CPU_ISA_IV;
		c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
		             MIPS_CPU_DIVEC | MIPS_CPU_LLSC;
		c->tlbsize = 48;
		break;
	case PRID_IMP_R6000:
		c->cputype = CPU_R6000;
		c->isa_level = MIPS_CPU_ISA_II;
		c->options = MIPS_CPU_TLB | MIPS_CPU_FPU |
		             MIPS_CPU_LLSC;
		c->tlbsize = 32;
		break;
	case PRID_IMP_R6000A:
		c->cputype = CPU_R6000A;
		c->isa_level = MIPS_CPU_ISA_II;
		c->options = MIPS_CPU_TLB | MIPS_CPU_FPU |
		             MIPS_CPU_LLSC;
		c->tlbsize = 32;
		break;
	case PRID_IMP_RM7000:
		c->cputype = CPU_RM7000;
		c->isa_level = MIPS_CPU_ISA_IV;
		c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
		             MIPS_CPU_LLSC;
		/*
		 * Undocumented RM7000:  Bit 29 in the info register of
		 * the RM7000 v2.0 indicates if the TLB has 48 or 64
		 * entries.
		 *
		 * 29      1 =>    64 entry JTLB
		 *         0 =>    48 entry JTLB
		 */
		c->tlbsize = (read_c0_info() & (1 << 29)) ? 64 : 48;
		break;
	case PRID_IMP_RM9000:
		c->cputype = CPU_RM9000;
		c->isa_level = MIPS_CPU_ISA_IV;
		c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
		             MIPS_CPU_LLSC;
		/*
		 * Bit 29 in the info register of the RM9000
		 * indicates if the TLB has 48 or 64 entries.
		 *
		 * 29      1 =>    64 entry JTLB
		 *         0 =>    48 entry JTLB
		 */
		c->tlbsize = (read_c0_info() & (1 << 29)) ? 64 : 48;
		break;
	case PRID_IMP_R8000:
		c->cputype = CPU_R8000;
		c->isa_level = MIPS_CPU_ISA_IV;
		c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
		             MIPS_CPU_FPU | MIPS_CPU_32FPR |
		             MIPS_CPU_LLSC;
		c->tlbsize = 384;      /* has weird TLB: 3-way x 128 */
		break;
	case PRID_IMP_R10000:
		c->cputype = CPU_R10000;
		c->isa_level = MIPS_CPU_ISA_IV;
420
		c->options = MIPS_CPU_TLB | MIPS_CPU_4K_CACHE | MIPS_CPU_4KEX |
Linus Torvalds's avatar
Linus Torvalds committed
421
422
423
424
425
426
427
428
		             MIPS_CPU_FPU | MIPS_CPU_32FPR |
			     MIPS_CPU_COUNTER | MIPS_CPU_WATCH |
		             MIPS_CPU_LLSC;
		c->tlbsize = 64;
		break;
	case PRID_IMP_R12000:
		c->cputype = CPU_R12000;
		c->isa_level = MIPS_CPU_ISA_IV;
429
		c->options = MIPS_CPU_TLB | MIPS_CPU_4K_CACHE | MIPS_CPU_4KEX |
Linus Torvalds's avatar
Linus Torvalds committed
430
431
432
433
434
435
436
437
		             MIPS_CPU_FPU | MIPS_CPU_32FPR |
			     MIPS_CPU_COUNTER | MIPS_CPU_WATCH |
		             MIPS_CPU_LLSC;
		c->tlbsize = 64;
		break;
	}
}

438
static inline unsigned int decode_config0(struct cpuinfo_mips *c)
Linus Torvalds's avatar
Linus Torvalds committed
439
{
440
441
	unsigned int config0;
	int isa;
Linus Torvalds's avatar
Linus Torvalds committed
442

443
444
445
	config0 = read_c0_config();

	if (((config0 & MIPS_CONF_MT) >> 7) == 1)
446
		c->options |= MIPS_CPU_TLB;
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
	isa = (config0 & MIPS_CONF_AT) >> 13;
	switch (isa) {
	case 0:
		c->isa_level = MIPS_CPU_ISA_M32;
		break;
	case 2:
		c->isa_level = MIPS_CPU_ISA_M64;
		break;
	default:
		panic("Unsupported ISA type, cp0.config0.at: %d.", isa);
	}

	return config0 & MIPS_CONF_M;
}

static inline unsigned int decode_config1(struct cpuinfo_mips *c)
{
	unsigned int config1;
Linus Torvalds's avatar
Linus Torvalds committed
465
466

	config1 = read_c0_config1();
467
468
469
470

	if (config1 & MIPS_CONF1_MD)
		c->ases |= MIPS_ASE_MDMX;
	if (config1 & MIPS_CONF1_WR)
Linus Torvalds's avatar
Linus Torvalds committed
471
		c->options |= MIPS_CPU_WATCH;
472
473
474
	if (config1 & MIPS_CONF1_CA)
		c->ases |= MIPS_ASE_MIPS16;
	if (config1 & MIPS_CONF1_EP)
Linus Torvalds's avatar
Linus Torvalds committed
475
		c->options |= MIPS_CPU_EJTAG;
476
	if (config1 & MIPS_CONF1_FP) {
Linus Torvalds's avatar
Linus Torvalds committed
477
478
479
		c->options |= MIPS_CPU_FPU;
		c->options |= MIPS_CPU_32FPR;
	}
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
	if (cpu_has_tlb)
		c->tlbsize = ((config1 & MIPS_CONF1_TLBS) >> 25) + 1;

	return config1 & MIPS_CONF_M;
}

static inline unsigned int decode_config2(struct cpuinfo_mips *c)
{
	unsigned int config2;

	config2 = read_c0_config2();

	if (config2 & MIPS_CONF2_SL)
		c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT;

	return config2 & MIPS_CONF_M;
}

static inline unsigned int decode_config3(struct cpuinfo_mips *c)
{
	unsigned int config3;

	config3 = read_c0_config3();

	if (config3 & MIPS_CONF3_SM)
		c->ases |= MIPS_ASE_SMARTMIPS;
506
507
	if (config3 & MIPS_CONF3_DSP)
		c->ases |= MIPS_ASE_DSP;
508
509
510
511
512
513
	if (config3 & MIPS_CONF3_VINT)
		c->options |= MIPS_CPU_VINT;
	if (config3 & MIPS_CONF3_VEIC)
		c->options |= MIPS_CPU_VEIC;
	if (config3 & MIPS_CONF3_MT)
                c->ases |= MIPS_ASE_MIPSMT;
514
515
516
517
518
519
520

	return config3 & MIPS_CONF_M;
}

static inline void decode_configs(struct cpuinfo_mips *c)
{
	/* MIPS32 or MIPS64 compliant CPU.  */
521
522
	c->options = MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE | MIPS_CPU_COUNTER |
	             MIPS_CPU_DIVEC | MIPS_CPU_LLSC | MIPS_CPU_MCHECK;
523

Linus Torvalds's avatar
Linus Torvalds committed
524
525
	c->scache.flags = MIPS_CACHE_NOT_PRESENT;

526
527
528
529
530
531
532
533
534
	/* Read Config registers.  */
	if (!decode_config0(c))
		return;			/* actually worth a panic() */
	if (!decode_config1(c))
		return;
	if (!decode_config2(c))
		return;
	if (!decode_config3(c))
		return;
Linus Torvalds's avatar
Linus Torvalds committed
535
536
537
538
}

static inline void cpu_probe_mips(struct cpuinfo_mips *c)
{
539
	decode_configs(c);
Linus Torvalds's avatar
Linus Torvalds committed
540
541
542
543
544
545
546
	switch (c->processor_id & 0xff00) {
	case PRID_IMP_4KC:
		c->cputype = CPU_4KC;
		break;
	case PRID_IMP_4KEC:
		c->cputype = CPU_4KEC;
		break;
547
548
549
	case PRID_IMP_4KECR2:
		c->cputype = CPU_4KEC;
		break;
Linus Torvalds's avatar
Linus Torvalds committed
550
	case PRID_IMP_4KSC:
551
	case PRID_IMP_4KSD:
Linus Torvalds's avatar
Linus Torvalds committed
552
553
554
555
556
557
558
559
560
		c->cputype = CPU_4KSC;
		break;
	case PRID_IMP_5KC:
		c->cputype = CPU_5KC;
		break;
	case PRID_IMP_20KC:
		c->cputype = CPU_20KC;
		break;
	case PRID_IMP_24K:
561
	case PRID_IMP_24KE:
Linus Torvalds's avatar
Linus Torvalds committed
562
563
564
565
566
567
568
		c->cputype = CPU_24K;
		break;
	case PRID_IMP_25KF:
		c->cputype = CPU_25KF;
		/* Probe for L2 cache */
		c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT;
		break;
Ralf Baechle's avatar
Ralf Baechle committed
569
570
571
572
	case PRID_IMP_34K:
		c->cputype = CPU_34K;
		c->isa_level = MIPS_CPU_ISA_M32;
		break;
Linus Torvalds's avatar
Linus Torvalds committed
573
574
575
576
577
	}
}

static inline void cpu_probe_alchemy(struct cpuinfo_mips *c)
{
578
	decode_configs(c);
Linus Torvalds's avatar
Linus Torvalds committed
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
	switch (c->processor_id & 0xff00) {
	case PRID_IMP_AU1_REV1:
	case PRID_IMP_AU1_REV2:
		switch ((c->processor_id >> 24) & 0xff) {
		case 0:
 			c->cputype = CPU_AU1000;
			break;
		case 1:
			c->cputype = CPU_AU1500;
			break;
		case 2:
			c->cputype = CPU_AU1100;
			break;
		case 3:
			c->cputype = CPU_AU1550;
			break;
Pete Popov's avatar
Pete Popov committed
595
596
597
		case 4:
			c->cputype = CPU_AU1200;
			break;
Linus Torvalds's avatar
Linus Torvalds committed
598
599
600
601
602
603
604
605
606
607
		default:
			panic("Unknown Au Core!");
			break;
		}
		break;
	}
}

static inline void cpu_probe_sibyte(struct cpuinfo_mips *c)
{
608
	decode_configs(c);
609
610
611
612
613
614

	/*
	 * For historical reasons the SB1 comes with it's own variant of
	 * cache code which eventually will be folded into c-r4k.c.  Until
	 * then we pretend it's got it's own cache architecture.
	 */
Andrew Isaacson's avatar
Andrew Isaacson committed
615
	c->options &= ~MIPS_CPU_4K_CACHE;
616
617
	c->options |= MIPS_CPU_SB1_CACHE;

Linus Torvalds's avatar
Linus Torvalds committed
618
619
620
	switch (c->processor_id & 0xff00) {
	case PRID_IMP_SB1:
		c->cputype = CPU_SB1;
621
#ifdef CONFIG_SB1_PASS_1_WORKAROUNDS
Linus Torvalds's avatar
Linus Torvalds committed
622
		/* FPU in pass1 is known to have issues. */
623
		c->options &= ~(MIPS_CPU_FPU | MIPS_CPU_32FPR);
Linus Torvalds's avatar
Linus Torvalds committed
624
625
#endif
		break;
Andrew Isaacson's avatar
Andrew Isaacson committed
626
627
628
	case PRID_IMP_SB1A:
		c->cputype = CPU_SB1A;
		break;
Linus Torvalds's avatar
Linus Torvalds committed
629
630
631
632
633
	}
}

static inline void cpu_probe_sandcraft(struct cpuinfo_mips *c)
{
634
	decode_configs(c);
Linus Torvalds's avatar
Linus Torvalds committed
635
636
637
638
639
640
641
642
643
	switch (c->processor_id & 0xff00) {
	case PRID_IMP_SR71000:
		c->cputype = CPU_SR71000;
		c->scache.ways = 8;
		c->tlbsize = 64;
		break;
	}
}

644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
static inline void cpu_probe_philips(struct cpuinfo_mips *c)
{
	decode_configs(c);
	switch (c->processor_id & 0xff00) {
	case PRID_IMP_PR4450:
		c->cputype = CPU_PR4450;
		c->isa_level = MIPS_CPU_ISA_M32;
		break;
	default:
		panic("Unknown Philips Core!"); /* REVISIT: die? */
		break;
	}
}


Linus Torvalds's avatar
Linus Torvalds committed
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
__init void cpu_probe(void)
{
	struct cpuinfo_mips *c = &current_cpu_data;

	c->processor_id	= PRID_IMP_UNKNOWN;
	c->fpu_id	= FPIR_IMP_NONE;
	c->cputype	= CPU_UNKNOWN;

	c->processor_id = read_c0_prid();
	switch (c->processor_id & 0xff0000) {
	case PRID_COMP_LEGACY:
		cpu_probe_legacy(c);
		break;
	case PRID_COMP_MIPS:
		cpu_probe_mips(c);
		break;
	case PRID_COMP_ALCHEMY:
		cpu_probe_alchemy(c);
		break;
	case PRID_COMP_SIBYTE:
		cpu_probe_sibyte(c);
		break;
	case PRID_COMP_SANDCRAFT:
		cpu_probe_sandcraft(c);
		break;
684
685
686
 	case PRID_COMP_PHILIPS:
		cpu_probe_philips(c);
 		break;
Linus Torvalds's avatar
Linus Torvalds committed
687
688
689
	default:
		c->cputype = CPU_UNKNOWN;
	}
690
	if (c->options & MIPS_CPU_FPU) {
Linus Torvalds's avatar
Linus Torvalds committed
691
		c->fpu_id = cpu_get_fpu_id();
692
693
694
695
696
697
698

		if (c->isa_level == MIPS_CPU_ISA_M32 ||
		    c->isa_level == MIPS_CPU_ISA_M64) {
			if (c->fpu_id & MIPS_FPIR_3D)
				c->ases |= MIPS_ASE_MIPS3D;
		}
	}
Linus Torvalds's avatar
Linus Torvalds committed
699
700
701
702
703
704
705
706
707
708
}

__init void cpu_report(void)
{
	struct cpuinfo_mips *c = &current_cpu_data;

	printk("CPU revision is: %08x\n", c->processor_id);
	if (c->options & MIPS_CPU_FPU)
		printk("FPU revision is: %08x\n", c->fpu_id);
}