cpu-probe.c 22.6 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4
/*
 * Processor capabilities determination functions.
 *
 * Copyright (C) xxxx  the Anonymous
5
 * Copyright (C) 1994 - 2006 Ralf Baechle
6 7
 * Copyright (C) 2003, 2004  Maciej W. Rozycki
 * Copyright (C) 2001, 2004  MIPS Inc.
L
Linus Torvalds 已提交
8 9 10 11 12 13 14 15 16
 *
 * 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/init.h>
#include <linux/kernel.h>
#include <linux/ptrace.h>
17
#include <linux/smp.h>
L
Linus Torvalds 已提交
18 19
#include <linux/stddef.h>

20
#include <asm/bugs.h>
L
Linus Torvalds 已提交
21 22 23 24
#include <asm/cpu.h>
#include <asm/fpu.h>
#include <asm/mipsregs.h>
#include <asm/system.h>
25
#include <asm/watch.h>
L
Linus Torvalds 已提交
26 27 28 29 30 31 32 33

/*
 * 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.
 */
34
void (*cpu_wait)(void);
L
Linus Torvalds 已提交
35 36 37 38 39 40 41 42 43

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

static void r39xx_wait(void)
{
44 45 46 47
	local_irq_disable();
	if (!need_resched())
		write_c0_conf(read_c0_conf() | TX39_CONF_HALT);
	local_irq_enable();
L
Linus Torvalds 已提交
48 49
}

50
extern void r4k_wait(void);
51 52 53 54 55 56 57 58

/*
 * This variant is preferable as it allows testing need_resched and going to
 * sleep depending on the outcome atomically.  Unfortunately the "It is
 * implementation-dependent whether the pipeline restarts when a non-enabled
 * interrupt is requested" restriction in the MIPS32/MIPS64 architecture makes
 * using this version a gamble.
 */
59
void r4k_wait_irqoff(void)
60 61 62
{
	local_irq_disable();
	if (!need_resched())
63 64
		__asm__("	.set	push		\n"
			"	.set	mips3		\n"
65
			"	wait			\n"
66
			"	.set	pop		\n");
67
	local_irq_enable();
68 69 70
	__asm__(" 	.globl __pastwait	\n"
		"__pastwait:			\n");
	return;
L
Linus Torvalds 已提交
71 72
}

73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
/*
 * The RM7000 variant has to handle erratum 38.  The workaround is to not
 * have any pending stores when the WAIT instruction is executed.
 */
static void rm7k_wait_irqoff(void)
{
	local_irq_disable();
	if (!need_resched())
		__asm__(
		"	.set	push					\n"
		"	.set	mips3					\n"
		"	.set	noat					\n"
		"	mfc0	$1, $12					\n"
		"	sync						\n"
		"	mtc0	$1, $12		# stalls until W stage	\n"
		"	wait						\n"
		"	mtc0	$1, $12		# stalls until W stage	\n"
		"	.set	pop					\n");
	local_irq_enable();
}

94 95 96 97 98
/*
 * The Au1xxx wait is available only if using 32khz counter or
 * external timer source, but specifically not CP0 Counter.
 * alchemy/common/time.c may override cpu_wait!
 */
99
static void au1k_wait(void)
L
Linus Torvalds 已提交
100
{
101 102 103 104 105 106 107 108 109 110 111
	__asm__("	.set	mips3			\n"
		"	cache	0x14, 0(%0)		\n"
		"	cache	0x14, 32(%0)		\n"
		"	sync				\n"
		"	nop				\n"
		"	wait				\n"
		"	nop				\n"
		"	nop				\n"
		"	nop				\n"
		"	nop				\n"
		"	.set	mips0			\n"
R
Ralf Baechle 已提交
112
		: : "r" (au1k_wait));
L
Linus Torvalds 已提交
113 114
}

115
static int __initdata nowait;
116

117
static int __init wait_disable(char *s)
118 119 120 121 122 123 124 125
{
	nowait = 1;

	return 1;
}

__setup("nowait", wait_disable);

126
void __init check_wait(void)
L
Linus Torvalds 已提交
127 128 129
{
	struct cpuinfo_mips *c = &current_cpu_data;

130
	if (nowait) {
131
		printk("Wait instruction disabled.\n");
132 133 134
		return;
	}

L
Linus Torvalds 已提交
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
	switch (c->cputype) {
	case CPU_R3081:
	case CPU_R3081E:
		cpu_wait = r3081_wait;
		break;
	case CPU_TX3927:
		cpu_wait = r39xx_wait;
		break;
	case CPU_R4200:
/*	case CPU_R4300: */
	case CPU_R4600:
	case CPU_R4640:
	case CPU_R4650:
	case CPU_R4700:
	case CPU_R5000:
150
	case CPU_R5500:
L
Linus Torvalds 已提交
151 152 153 154 155 156
	case CPU_NEVADA:
	case CPU_4KC:
	case CPU_4KEC:
	case CPU_4KSC:
	case CPU_5KC:
	case CPU_25KF:
157
	case CPU_PR4450:
158
	case CPU_BCM3302:
159
	case CPU_CAVIUM_OCTEON:
160 161 162
		cpu_wait = r4k_wait;
		break;

163 164 165 166
	case CPU_RM7000:
		cpu_wait = rm7k_wait_irqoff;
		break;

167
	case CPU_24K:
R
Ralf Baechle 已提交
168
	case CPU_34K:
169
	case CPU_1004K:
170 171 172 173 174
		cpu_wait = r4k_wait;
		if (read_c0_config7() & MIPS_CONF7_WII)
			cpu_wait = r4k_wait_irqoff;
		break;

175
	case CPU_74K:
L
Linus Torvalds 已提交
176
		cpu_wait = r4k_wait;
177 178
		if ((c->processor_id & 0xff) >= PRID_REV_ENCODE_332(2, 1, 0))
			cpu_wait = r4k_wait_irqoff;
L
Linus Torvalds 已提交
179
		break;
180

181 182 183
	case CPU_TX49XX:
		cpu_wait = r4k_wait_irqoff;
		break;
184
	case CPU_ALCHEMY:
185
		cpu_wait = au1k_wait;
L
Linus Torvalds 已提交
186
		break;
187 188 189 190 191 192 193 194 195
	case CPU_20KC:
		/*
		 * WAIT on Rev1.0 has E1, E2, E3 and E16.
		 * WAIT on Rev2.0 and Rev3.0 has E16.
		 * Rev3.1 WAIT is nop, why bother
		 */
		if ((c->processor_id & 0xff) <= 0x64)
			break;

196 197 198 199 200 201 202 203
		/*
		 * Another rev is incremeting c0_count at a reduced clock
		 * rate while in WAIT mode.  So we basically have the choice
		 * between using the cp0 timer as clocksource or avoiding
		 * the WAIT instruction.  Until more details are known,
		 * disable the use of WAIT for 20Kc entirely.
		   cpu_wait = r4k_wait;
		 */
204
		break;
205
	case CPU_RM9000:
206
		if ((c->processor_id & 0x00ff) >= 0x40)
207 208
			cpu_wait = r4k_wait;
		break;
L
Linus Torvalds 已提交
209 210 211 212 213
	default:
		break;
	}
}

M
Marc St-Jean 已提交
214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
static inline void check_errata(void)
{
	struct cpuinfo_mips *c = &current_cpu_data;

	switch (c->cputype) {
	case CPU_34K:
		/*
		 * Erratum "RPS May Cause Incorrect Instruction Execution"
		 * This code only handles VPE0, any SMP/SMTC/RTOS code
		 * making use of VPE1 will be responsable for that VPE.
		 */
		if ((c->processor_id & PRID_REV_MASK) <= PRID_REV_34K_V1_0_2)
			write_c0_config7(read_c0_config7() | MIPS_CONF7_RPS);
		break;
	default:
		break;
	}
}

L
Linus Torvalds 已提交
233 234
void __init check_bugs32(void)
{
M
Marc St-Jean 已提交
235
	check_errata();
L
Linus Torvalds 已提交
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
}

/*
 * 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);
}

R
Ralf Baechle 已提交
282
#define R4K_OPTS (MIPS_CPU_TLB | MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE \
L
Linus Torvalds 已提交
283 284
		| MIPS_CPU_COUNTER)

285
static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
L
Linus Torvalds 已提交
286 287 288 289
{
	switch (c->processor_id & 0xff00) {
	case PRID_IMP_R2000:
		c->cputype = CPU_R2000;
290
		__cpu_name[cpu] = "R2000";
L
Linus Torvalds 已提交
291
		c->isa_level = MIPS_CPU_ISA_I;
R
Ralf Baechle 已提交
292 293
		c->options = MIPS_CPU_TLB | MIPS_CPU_3K_CACHE |
		             MIPS_CPU_NOFPUEX;
L
Linus Torvalds 已提交
294 295 296 297 298
		if (__cpu_has_fpu())
			c->options |= MIPS_CPU_FPU;
		c->tlbsize = 64;
		break;
	case PRID_IMP_R3000:
299 300
		if ((c->processor_id & 0xff) == PRID_REV_R3000A) {
			if (cpu_has_confreg()) {
L
Linus Torvalds 已提交
301
				c->cputype = CPU_R3081E;
302 303
				__cpu_name[cpu] = "R3081";
			} else {
L
Linus Torvalds 已提交
304
				c->cputype = CPU_R3000A;
305 306 307 308
				__cpu_name[cpu] = "R3000A";
			}
			break;
		} else {
L
Linus Torvalds 已提交
309
			c->cputype = CPU_R3000;
310 311
			__cpu_name[cpu] = "R3000";
		}
L
Linus Torvalds 已提交
312
		c->isa_level = MIPS_CPU_ISA_I;
R
Ralf Baechle 已提交
313 314
		c->options = MIPS_CPU_TLB | MIPS_CPU_3K_CACHE |
		             MIPS_CPU_NOFPUEX;
L
Linus Torvalds 已提交
315 316 317 318 319 320
		if (__cpu_has_fpu())
			c->options |= MIPS_CPU_FPU;
		c->tlbsize = 64;
		break;
	case PRID_IMP_R4000:
		if (read_c0_config() & CONF_SC) {
321
			if ((c->processor_id & 0xff) >= PRID_REV_R4400) {
L
Linus Torvalds 已提交
322
				c->cputype = CPU_R4400PC;
323 324
				__cpu_name[cpu] = "R4400PC";
			} else {
L
Linus Torvalds 已提交
325
				c->cputype = CPU_R4000PC;
326 327
				__cpu_name[cpu] = "R4000PC";
			}
L
Linus Torvalds 已提交
328
		} else {
329
			if ((c->processor_id & 0xff) >= PRID_REV_R4400) {
L
Linus Torvalds 已提交
330
				c->cputype = CPU_R4400SC;
331 332
				__cpu_name[cpu] = "R4400SC";
			} else {
L
Linus Torvalds 已提交
333
				c->cputype = CPU_R4000SC;
334 335
				__cpu_name[cpu] = "R4000SC";
			}
L
Linus Torvalds 已提交
336 337 338 339 340 341 342 343 344 345 346 347
		}

		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;
348
			__cpu_name[cpu] = "NEC VR4111";
L
Linus Torvalds 已提交
349 350 351
			break;
		case PRID_REV_VR4121:
			c->cputype = CPU_VR4121;
352
			__cpu_name[cpu] = "NEC VR4121";
L
Linus Torvalds 已提交
353 354
			break;
		case PRID_REV_VR4122:
355
			if ((c->processor_id & 0xf) < 0x3) {
L
Linus Torvalds 已提交
356
				c->cputype = CPU_VR4122;
357 358
				__cpu_name[cpu] = "NEC VR4122";
			} else {
L
Linus Torvalds 已提交
359
				c->cputype = CPU_VR4181A;
360 361
				__cpu_name[cpu] = "NEC VR4181A";
			}
L
Linus Torvalds 已提交
362 363
			break;
		case PRID_REV_VR4130:
364
			if ((c->processor_id & 0xf) < 0x4) {
L
Linus Torvalds 已提交
365
				c->cputype = CPU_VR4131;
366 367
				__cpu_name[cpu] = "NEC VR4131";
			} else {
L
Linus Torvalds 已提交
368
				c->cputype = CPU_VR4133;
369 370
				__cpu_name[cpu] = "NEC VR4133";
			}
L
Linus Torvalds 已提交
371 372 373 374
			break;
		default:
			printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n");
			c->cputype = CPU_VR41XX;
375
			__cpu_name[cpu] = "NEC Vr41xx";
L
Linus Torvalds 已提交
376 377 378 379 380 381 382 383
			break;
		}
		c->isa_level = MIPS_CPU_ISA_III;
		c->options = R4K_OPTS;
		c->tlbsize = 32;
		break;
	case PRID_IMP_R4300:
		c->cputype = CPU_R4300;
384
		__cpu_name[cpu] = "R4300";
L
Linus Torvalds 已提交
385 386 387 388 389 390 391
		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;
392
		__cpu_name[cpu] = "R4600";
L
Linus Torvalds 已提交
393
		c->isa_level = MIPS_CPU_ISA_III;
T
Thiemo Seufer 已提交
394 395
		c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
			     MIPS_CPU_LLSC;
L
Linus Torvalds 已提交
396 397 398 399 400 401 402 403 404 405
		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.
		 */
406
		c->cputype = CPU_R4650;
407
		__cpu_name[cpu] = "R4650";
L
Linus Torvalds 已提交
408 409 410 411 412 413 414
	 	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;
R
Ralf Baechle 已提交
415
		c->options = MIPS_CPU_TLB | MIPS_CPU_TX39_CACHE;
L
Linus Torvalds 已提交
416 417 418

		if ((c->processor_id & 0xf0) == (PRID_REV_TX3927 & 0xf0)) {
			c->cputype = CPU_TX3927;
419
			__cpu_name[cpu] = "TX3927";
L
Linus Torvalds 已提交
420 421 422 423 424
			c->tlbsize = 64;
		} else {
			switch (c->processor_id & 0xff) {
			case PRID_REV_TX3912:
				c->cputype = CPU_TX3912;
425
				__cpu_name[cpu] = "TX3912";
L
Linus Torvalds 已提交
426 427 428 429
				c->tlbsize = 32;
				break;
			case PRID_REV_TX3922:
				c->cputype = CPU_TX3922;
430
				__cpu_name[cpu] = "TX3922";
L
Linus Torvalds 已提交
431 432 433 434 435 436 437
				c->tlbsize = 64;
				break;
			}
		}
		break;
	case PRID_IMP_R4700:
		c->cputype = CPU_R4700;
438
		__cpu_name[cpu] = "R4700";
L
Linus Torvalds 已提交
439 440 441 442 443 444 445
		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;
446
		__cpu_name[cpu] = "R49XX";
L
Linus Torvalds 已提交
447 448 449 450 451 452 453 454
		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;
455
		__cpu_name[cpu] = "R5000";
L
Linus Torvalds 已提交
456 457 458 459 460 461 462
		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;
463
		__cpu_name[cpu] = "R5432";
L
Linus Torvalds 已提交
464 465 466 467 468 469 470
		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;
471
		__cpu_name[cpu] = "R5500";
L
Linus Torvalds 已提交
472 473 474 475 476 477 478
		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;
479
		__cpu_name[cpu] = "Nevada";
L
Linus Torvalds 已提交
480 481 482 483 484 485 486
		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;
487
		__cpu_name[cpu] = "R6000";
L
Linus Torvalds 已提交
488 489 490 491 492 493 494
		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;
495
		__cpu_name[cpu] = "R6000A";
L
Linus Torvalds 已提交
496 497 498 499 500 501 502
		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;
503
		__cpu_name[cpu] = "RM7000";
L
Linus Torvalds 已提交
504 505 506 507 508 509 510 511 512 513 514 515 516 517 518
		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;
519
		__cpu_name[cpu] = "RM9000";
L
Linus Torvalds 已提交
520 521 522 523 524 525 526 527 528 529 530 531 532 533
		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;
534
		__cpu_name[cpu] = "RM8000";
L
Linus Torvalds 已提交
535 536 537 538 539 540 541 542
		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;
543
		__cpu_name[cpu] = "R10000";
L
Linus Torvalds 已提交
544
		c->isa_level = MIPS_CPU_ISA_IV;
545
		c->options = MIPS_CPU_TLB | MIPS_CPU_4K_CACHE | MIPS_CPU_4KEX |
L
Linus Torvalds 已提交
546 547 548 549 550 551 552
		             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;
553
		__cpu_name[cpu] = "R12000";
L
Linus Torvalds 已提交
554
		c->isa_level = MIPS_CPU_ISA_IV;
555
		c->options = MIPS_CPU_TLB | MIPS_CPU_4K_CACHE | MIPS_CPU_4KEX |
L
Linus Torvalds 已提交
556 557 558 559 560
		             MIPS_CPU_FPU | MIPS_CPU_32FPR |
			     MIPS_CPU_COUNTER | MIPS_CPU_WATCH |
		             MIPS_CPU_LLSC;
		c->tlbsize = 64;
		break;
K
Kumba 已提交
561 562
	case PRID_IMP_R14000:
		c->cputype = CPU_R14000;
563
		__cpu_name[cpu] = "R14000";
K
Kumba 已提交
564 565 566 567 568 569 570
		c->isa_level = MIPS_CPU_ISA_IV;
		c->options = MIPS_CPU_TLB | MIPS_CPU_4K_CACHE | MIPS_CPU_4KEX |
		             MIPS_CPU_FPU | MIPS_CPU_32FPR |
			     MIPS_CPU_COUNTER | MIPS_CPU_WATCH |
		             MIPS_CPU_LLSC;
		c->tlbsize = 64;
		break;
571 572
	case PRID_IMP_LOONGSON2:
		c->cputype = CPU_LOONGSON2;
573
		__cpu_name[cpu] = "ICT Loongson-2";
574 575 576 577 578 579
		c->isa_level = MIPS_CPU_ISA_III;
		c->options = R4K_OPTS |
			     MIPS_CPU_FPU | MIPS_CPU_LLSC |
			     MIPS_CPU_32FPR;
		c->tlbsize = 64;
		break;
L
Linus Torvalds 已提交
580 581 582
	}
}

583
static char unknown_isa[] __cpuinitdata = KERN_ERR \
584 585
	"Unsupported ISA type, c0.config0: %d.";

586
static inline unsigned int decode_config0(struct cpuinfo_mips *c)
L
Linus Torvalds 已提交
587
{
588 589
	unsigned int config0;
	int isa;
L
Linus Torvalds 已提交
590

591 592 593
	config0 = read_c0_config();

	if (((config0 & MIPS_CONF_MT) >> 7) == 1)
R
Ralf Baechle 已提交
594
		c->options |= MIPS_CPU_TLB;
595 596 597
	isa = (config0 & MIPS_CONF_AT) >> 13;
	switch (isa) {
	case 0:
598
		switch ((config0 & MIPS_CONF_AR) >> 10) {
599 600 601 602 603 604 605 606 607
		case 0:
			c->isa_level = MIPS_CPU_ISA_M32R1;
			break;
		case 1:
			c->isa_level = MIPS_CPU_ISA_M32R2;
			break;
		default:
			goto unknown;
		}
608 609
		break;
	case 2:
610
		switch ((config0 & MIPS_CONF_AR) >> 10) {
611 612 613 614 615 616 617 618 619
		case 0:
			c->isa_level = MIPS_CPU_ISA_M64R1;
			break;
		case 1:
			c->isa_level = MIPS_CPU_ISA_M64R2;
			break;
		default:
			goto unknown;
		}
620 621
		break;
	default:
622
		goto unknown;
623 624 625
	}

	return config0 & MIPS_CONF_M;
626 627 628

unknown:
	panic(unknown_isa, config0);
629 630 631 632 633
}

static inline unsigned int decode_config1(struct cpuinfo_mips *c)
{
	unsigned int config1;
L
Linus Torvalds 已提交
634 635

	config1 = read_c0_config1();
636 637 638 639

	if (config1 & MIPS_CONF1_MD)
		c->ases |= MIPS_ASE_MDMX;
	if (config1 & MIPS_CONF1_WR)
L
Linus Torvalds 已提交
640
		c->options |= MIPS_CPU_WATCH;
641 642 643
	if (config1 & MIPS_CONF1_CA)
		c->ases |= MIPS_ASE_MIPS16;
	if (config1 & MIPS_CONF1_EP)
L
Linus Torvalds 已提交
644
		c->options |= MIPS_CPU_EJTAG;
645
	if (config1 & MIPS_CONF1_FP) {
L
Linus Torvalds 已提交
646 647 648
		c->options |= MIPS_CPU_FPU;
		c->options |= MIPS_CPU_32FPR;
	}
649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674
	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;
675 676
	if (config3 & MIPS_CONF3_DSP)
		c->ases |= MIPS_ASE_DSP;
677 678 679 680 681
	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)
R
Ralf Baechle 已提交
682
	        c->ases |= MIPS_ASE_MIPSMT;
683 684
	if (config3 & MIPS_CONF3_ULRI)
		c->options |= MIPS_CPU_ULRI;
685 686 687 688

	return config3 & MIPS_CONF_M;
}

689
static void __cpuinit decode_configs(struct cpuinfo_mips *c)
690
{
691 692
	int ok;

693
	/* MIPS32 or MIPS64 compliant CPU.  */
R
Ralf Baechle 已提交
694 695
	c->options = MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE | MIPS_CPU_COUNTER |
	             MIPS_CPU_DIVEC | MIPS_CPU_LLSC | MIPS_CPU_MCHECK;
696

L
Linus Torvalds 已提交
697 698
	c->scache.flags = MIPS_CACHE_NOT_PRESENT;

699 700 701 702 703 704 705 706 707 708
	ok = decode_config0(c);			/* Read Config registers.  */
	BUG_ON(!ok);				/* Arch spec violation!  */
	if (ok)
		ok = decode_config1(c);
	if (ok)
		ok = decode_config2(c);
	if (ok)
		ok = decode_config3(c);

	mips_probe_watch_registers(c);
L
Linus Torvalds 已提交
709 710
}

C
Chris Dearman 已提交
711 712 713 714 715 716
#ifdef CONFIG_CPU_MIPSR2
extern void spram_config(void);
#else
static inline void spram_config(void) {}
#endif

717
static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu)
L
Linus Torvalds 已提交
718
{
719
	decode_configs(c);
L
Linus Torvalds 已提交
720 721 722
	switch (c->processor_id & 0xff00) {
	case PRID_IMP_4KC:
		c->cputype = CPU_4KC;
723
		__cpu_name[cpu] = "MIPS 4Kc";
L
Linus Torvalds 已提交
724 725 726
		break;
	case PRID_IMP_4KEC:
		c->cputype = CPU_4KEC;
727
		__cpu_name[cpu] = "MIPS 4KEc";
L
Linus Torvalds 已提交
728
		break;
729 730
	case PRID_IMP_4KECR2:
		c->cputype = CPU_4KEC;
731
		__cpu_name[cpu] = "MIPS 4KEc";
732
		break;
L
Linus Torvalds 已提交
733
	case PRID_IMP_4KSC:
R
Ralf Baechle 已提交
734
	case PRID_IMP_4KSD:
L
Linus Torvalds 已提交
735
		c->cputype = CPU_4KSC;
736
		__cpu_name[cpu] = "MIPS 4KSc";
L
Linus Torvalds 已提交
737 738 739
		break;
	case PRID_IMP_5KC:
		c->cputype = CPU_5KC;
740
		__cpu_name[cpu] = "MIPS 5Kc";
L
Linus Torvalds 已提交
741 742 743
		break;
	case PRID_IMP_20KC:
		c->cputype = CPU_20KC;
744
		__cpu_name[cpu] = "MIPS 20Kc";
L
Linus Torvalds 已提交
745 746
		break;
	case PRID_IMP_24K:
747
	case PRID_IMP_24KE:
L
Linus Torvalds 已提交
748
		c->cputype = CPU_24K;
749
		__cpu_name[cpu] = "MIPS 24Kc";
L
Linus Torvalds 已提交
750 751 752
		break;
	case PRID_IMP_25KF:
		c->cputype = CPU_25KF;
753
		__cpu_name[cpu] = "MIPS 25Kc";
L
Linus Torvalds 已提交
754
		break;
R
Ralf Baechle 已提交
755 756
	case PRID_IMP_34K:
		c->cputype = CPU_34K;
757
		__cpu_name[cpu] = "MIPS 34Kc";
R
Ralf Baechle 已提交
758
		break;
759 760
	case PRID_IMP_74K:
		c->cputype = CPU_74K;
761
		__cpu_name[cpu] = "MIPS 74Kc";
762
		break;
763 764
	case PRID_IMP_1004K:
		c->cputype = CPU_1004K;
765
		__cpu_name[cpu] = "MIPS 1004Kc";
766
		break;
L
Linus Torvalds 已提交
767
	}
C
Chris Dearman 已提交
768 769

	spram_config();
L
Linus Torvalds 已提交
770 771
}

772
static inline void cpu_probe_alchemy(struct cpuinfo_mips *c, unsigned int cpu)
L
Linus Torvalds 已提交
773
{
774
	decode_configs(c);
L
Linus Torvalds 已提交
775 776 777
	switch (c->processor_id & 0xff00) {
	case PRID_IMP_AU1_REV1:
	case PRID_IMP_AU1_REV2:
778
		c->cputype = CPU_ALCHEMY;
L
Linus Torvalds 已提交
779 780
		switch ((c->processor_id >> 24) & 0xff) {
		case 0:
781
			__cpu_name[cpu] = "Au1000";
L
Linus Torvalds 已提交
782 783
			break;
		case 1:
784
			__cpu_name[cpu] = "Au1500";
L
Linus Torvalds 已提交
785 786
			break;
		case 2:
787
			__cpu_name[cpu] = "Au1100";
L
Linus Torvalds 已提交
788 789
			break;
		case 3:
790
			__cpu_name[cpu] = "Au1550";
L
Linus Torvalds 已提交
791
			break;
P
Pete Popov 已提交
792
		case 4:
793
			__cpu_name[cpu] = "Au1200";
794
			if ((c->processor_id & 0xff) == 2)
795
				__cpu_name[cpu] = "Au1250";
796 797
			break;
		case 5:
798
			__cpu_name[cpu] = "Au1210";
P
Pete Popov 已提交
799
			break;
L
Linus Torvalds 已提交
800
		default:
801
			__cpu_name[cpu] = "Au1xxx";
L
Linus Torvalds 已提交
802 803 804 805 806 807
			break;
		}
		break;
	}
}

808
static inline void cpu_probe_sibyte(struct cpuinfo_mips *c, unsigned int cpu)
L
Linus Torvalds 已提交
809
{
810
	decode_configs(c);
R
Ralf Baechle 已提交
811

L
Linus Torvalds 已提交
812 813 814
	switch (c->processor_id & 0xff00) {
	case PRID_IMP_SB1:
		c->cputype = CPU_SB1;
815
		__cpu_name[cpu] = "SiByte SB1";
L
Linus Torvalds 已提交
816
		/* FPU in pass1 is known to have issues. */
817
		if ((c->processor_id & 0xff) < 0x02)
818
			c->options &= ~(MIPS_CPU_FPU | MIPS_CPU_32FPR);
L
Linus Torvalds 已提交
819
		break;
A
Andrew Isaacson 已提交
820 821
	case PRID_IMP_SB1A:
		c->cputype = CPU_SB1A;
822
		__cpu_name[cpu] = "SiByte SB1A";
A
Andrew Isaacson 已提交
823
		break;
L
Linus Torvalds 已提交
824 825 826
	}
}

827
static inline void cpu_probe_sandcraft(struct cpuinfo_mips *c, unsigned int cpu)
L
Linus Torvalds 已提交
828
{
829
	decode_configs(c);
L
Linus Torvalds 已提交
830 831 832
	switch (c->processor_id & 0xff00) {
	case PRID_IMP_SR71000:
		c->cputype = CPU_SR71000;
833
		__cpu_name[cpu] = "Sandcraft SR71000";
L
Linus Torvalds 已提交
834 835 836 837 838 839
		c->scache.ways = 8;
		c->tlbsize = 64;
		break;
	}
}

840
static inline void cpu_probe_nxp(struct cpuinfo_mips *c, unsigned int cpu)
841 842 843 844 845
{
	decode_configs(c);
	switch (c->processor_id & 0xff00) {
	case PRID_IMP_PR4450:
		c->cputype = CPU_PR4450;
846
		__cpu_name[cpu] = "Philips PR4450";
847
		c->isa_level = MIPS_CPU_ISA_M32R1;
848 849 850 851
		break;
	}
}

852
static inline void cpu_probe_broadcom(struct cpuinfo_mips *c, unsigned int cpu)
853 854 855 856 857
{
	decode_configs(c);
	switch (c->processor_id & 0xff00) {
	case PRID_IMP_BCM3302:
		c->cputype = CPU_BCM3302;
858
		__cpu_name[cpu] = "Broadcom BCM3302";
859 860 861
		break;
	case PRID_IMP_BCM4710:
		c->cputype = CPU_BCM4710;
862
		__cpu_name[cpu] = "Broadcom BCM4710";
863 864 865 866
		break;
	}
}

867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887
static inline void cpu_probe_cavium(struct cpuinfo_mips *c, unsigned int cpu)
{
	decode_configs(c);
	switch (c->processor_id & 0xff00) {
	case PRID_IMP_CAVIUM_CN38XX:
	case PRID_IMP_CAVIUM_CN31XX:
	case PRID_IMP_CAVIUM_CN30XX:
	case PRID_IMP_CAVIUM_CN58XX:
	case PRID_IMP_CAVIUM_CN56XX:
	case PRID_IMP_CAVIUM_CN50XX:
	case PRID_IMP_CAVIUM_CN52XX:
		c->cputype = CPU_CAVIUM_OCTEON;
		__cpu_name[cpu] = "Cavium Octeon";
		break;
	default:
		printk(KERN_INFO "Unknown Octeon chip!\n");
		c->cputype = CPU_UNKNOWN;
		break;
	}
}

888 889
const char *__cpu_name[NR_CPUS];

890
__cpuinit void cpu_probe(void)
L
Linus Torvalds 已提交
891 892
{
	struct cpuinfo_mips *c = &current_cpu_data;
893
	unsigned int cpu = smp_processor_id();
L
Linus Torvalds 已提交
894 895 896 897 898 899 900 901

	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:
902
		cpu_probe_legacy(c, cpu);
L
Linus Torvalds 已提交
903 904
		break;
	case PRID_COMP_MIPS:
905
		cpu_probe_mips(c, cpu);
L
Linus Torvalds 已提交
906 907
		break;
	case PRID_COMP_ALCHEMY:
908
		cpu_probe_alchemy(c, cpu);
L
Linus Torvalds 已提交
909 910
		break;
	case PRID_COMP_SIBYTE:
911
		cpu_probe_sibyte(c, cpu);
L
Linus Torvalds 已提交
912
		break;
913
	case PRID_COMP_BROADCOM:
914
		cpu_probe_broadcom(c, cpu);
915
		break;
L
Linus Torvalds 已提交
916
	case PRID_COMP_SANDCRAFT:
917
		cpu_probe_sandcraft(c, cpu);
L
Linus Torvalds 已提交
918
		break;
919
	case PRID_COMP_NXP:
920
		cpu_probe_nxp(c, cpu);
921
		break;
922 923 924
	case PRID_COMP_CAVIUM:
		cpu_probe_cavium(c, cpu);
		break;
L
Linus Torvalds 已提交
925
	}
926

927 928 929
	BUG_ON(!__cpu_name[cpu]);
	BUG_ON(c->cputype == CPU_UNKNOWN);

930 931 932 933 934 935 936
	/*
	 * Platform code can force the cpu type to optimize code
	 * generation. In that case be sure the cpu type is correctly
	 * manually setup otherwise it could trigger some nasty bugs.
	 */
	BUG_ON(current_cpu_type() != c->cputype);

937
	if (c->options & MIPS_CPU_FPU) {
L
Linus Torvalds 已提交
938
		c->fpu_id = cpu_get_fpu_id();
939

940
		if (c->isa_level == MIPS_CPU_ISA_M32R1 ||
941 942 943
		    c->isa_level == MIPS_CPU_ISA_M32R2 ||
		    c->isa_level == MIPS_CPU_ISA_M64R1 ||
		    c->isa_level == MIPS_CPU_ISA_M64R2) {
944 945 946 947
			if (c->fpu_id & MIPS_FPIR_3D)
				c->ases |= MIPS_ASE_MIPS3D;
		}
	}
948

R
Ralf Baechle 已提交
949 950 951 952
	if (cpu_has_mips_r2)
		c->srsets = ((read_c0_srsctl() >> 26) & 0x0f) + 1;
	else
		c->srsets = 1;
L
Linus Torvalds 已提交
953 954
}

955
__cpuinit void cpu_report(void)
L
Linus Torvalds 已提交
956 957 958
{
	struct cpuinfo_mips *c = &current_cpu_data;

959 960
	printk(KERN_INFO "CPU revision is: %08x (%s)\n",
	       c->processor_id, cpu_name_string());
L
Linus Torvalds 已提交
961
	if (c->options & MIPS_CPU_FPU)
962
		printk(KERN_INFO "FPU revision is: %08x\n", c->fpu_id);
L
Linus Torvalds 已提交
963
}