cpu-probe.c 24.2 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
#include <linux/stddef.h>
19
#include <linux/module.h>
L
Linus Torvalds 已提交
20

21
#include <asm/bugs.h>
L
Linus Torvalds 已提交
22 23 24 25
#include <asm/cpu.h>
#include <asm/fpu.h>
#include <asm/mipsregs.h>
#include <asm/system.h>
26
#include <asm/watch.h>
27
#include <asm/spram.h>
L
Linus Torvalds 已提交
28 29 30 31 32 33 34
/*
 * 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.
 */
35
void (*cpu_wait)(void);
36
EXPORT_SYMBOL(cpu_wait);
L
Linus Torvalds 已提交
37 38 39 40 41 42 43 44 45

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

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

52
extern void r4k_wait(void);
53 54 55 56 57 58 59 60

/*
 * 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.
 */
61
void r4k_wait_irqoff(void)
62 63 64
{
	local_irq_disable();
	if (!need_resched())
65 66
		__asm__("	.set	push		\n"
			"	.set	mips3		\n"
67
			"	wait			\n"
68
			"	.set	pop		\n");
69
	local_irq_enable();
70 71 72
	__asm__(" 	.globl __pastwait	\n"
		"__pastwait:			\n");
	return;
L
Linus Torvalds 已提交
73 74
}

75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
/*
 * 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();
}

96 97 98 99 100
/*
 * 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!
 */
101
static void au1k_wait(void)
L
Linus Torvalds 已提交
102
{
103 104 105 106 107 108 109 110 111 112 113
	__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 已提交
114
		: : "r" (au1k_wait));
L
Linus Torvalds 已提交
115 116
}

117
static int __initdata nowait;
118

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

	return 1;
}

__setup("nowait", wait_disable);

128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
static int __cpuinitdata mips_fpu_disabled;

static int __init fpu_disable(char *s)
{
	cpu_data[0].options &= ~MIPS_CPU_FPU;
	mips_fpu_disabled = 1;

	return 1;
}

__setup("nofpu", fpu_disable);

int __cpuinitdata mips_dsp_disabled;

static int __init dsp_disable(char *s)
{
	cpu_data[0].ases &= ~MIPS_ASE_DSP;
	mips_dsp_disabled = 1;

	return 1;
}

__setup("nodsp", dsp_disable);

152
void __init check_wait(void)
L
Linus Torvalds 已提交
153 154 155
{
	struct cpuinfo_mips *c = &current_cpu_data;

156
	if (nowait) {
157
		printk("Wait instruction disabled.\n");
158 159 160
		return;
	}

L
Linus Torvalds 已提交
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
	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:
176
	case CPU_R5500:
L
Linus Torvalds 已提交
177 178 179 180 181 182
	case CPU_NEVADA:
	case CPU_4KC:
	case CPU_4KEC:
	case CPU_4KSC:
	case CPU_5KC:
	case CPU_25KF:
183
	case CPU_PR4450:
184
	case CPU_BCM3302:
185 186 187
	case CPU_BCM6338:
	case CPU_BCM6348:
	case CPU_BCM6358:
188
	case CPU_CAVIUM_OCTEON:
189
	case CPU_CAVIUM_OCTEON_PLUS:
190 191 192
		cpu_wait = r4k_wait;
		break;

193 194 195 196
	case CPU_RM7000:
		cpu_wait = rm7k_wait_irqoff;
		break;

197
	case CPU_24K:
R
Ralf Baechle 已提交
198
	case CPU_34K:
199
	case CPU_1004K:
200 201 202 203 204
		cpu_wait = r4k_wait;
		if (read_c0_config7() & MIPS_CONF7_WII)
			cpu_wait = r4k_wait_irqoff;
		break;

205
	case CPU_74K:
L
Linus Torvalds 已提交
206
		cpu_wait = r4k_wait;
207 208
		if ((c->processor_id & 0xff) >= PRID_REV_ENCODE_332(2, 1, 0))
			cpu_wait = r4k_wait_irqoff;
L
Linus Torvalds 已提交
209
		break;
210

211 212 213
	case CPU_TX49XX:
		cpu_wait = r4k_wait_irqoff;
		break;
214
	case CPU_ALCHEMY:
215
		cpu_wait = au1k_wait;
L
Linus Torvalds 已提交
216
		break;
217 218 219 220 221 222 223 224 225
	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;

226 227 228 229 230 231 232 233
		/*
		 * 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;
		 */
234
		break;
235
	case CPU_RM9000:
236
		if ((c->processor_id & 0x00ff) >= 0x40)
237 238
			cpu_wait = r4k_wait;
		break;
L
Linus Torvalds 已提交
239 240 241 242 243
	default:
		break;
	}
}

M
Marc St-Jean 已提交
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
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 已提交
263 264
void __init check_bugs32(void)
{
M
Marc St-Jean 已提交
265
	check_errata();
L
Linus Torvalds 已提交
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311
}

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

312 313 314
static inline void cpu_probe_vmbits(struct cpuinfo_mips *c)
{
#ifdef __NEED_VMBITS_PROBE
315
	write_c0_entryhi(0x3fffffffffffe000ULL);
316
	back_to_back_c0_hazard();
317
	c->vmbits = fls64(read_c0_entryhi() & 0x3fffffffffffe000ULL);
318 319 320
#endif
}

R
Ralf Baechle 已提交
321
#define R4K_OPTS (MIPS_CPU_TLB | MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE \
L
Linus Torvalds 已提交
322 323
		| MIPS_CPU_COUNTER)

324
static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
L
Linus Torvalds 已提交
325 326 327 328
{
	switch (c->processor_id & 0xff00) {
	case PRID_IMP_R2000:
		c->cputype = CPU_R2000;
329
		__cpu_name[cpu] = "R2000";
L
Linus Torvalds 已提交
330
		c->isa_level = MIPS_CPU_ISA_I;
R
Ralf Baechle 已提交
331 332
		c->options = MIPS_CPU_TLB | MIPS_CPU_3K_CACHE |
		             MIPS_CPU_NOFPUEX;
L
Linus Torvalds 已提交
333 334 335 336 337
		if (__cpu_has_fpu())
			c->options |= MIPS_CPU_FPU;
		c->tlbsize = 64;
		break;
	case PRID_IMP_R3000:
338 339
		if ((c->processor_id & 0xff) == PRID_REV_R3000A) {
			if (cpu_has_confreg()) {
L
Linus Torvalds 已提交
340
				c->cputype = CPU_R3081E;
341 342
				__cpu_name[cpu] = "R3081";
			} else {
L
Linus Torvalds 已提交
343
				c->cputype = CPU_R3000A;
344 345 346 347
				__cpu_name[cpu] = "R3000A";
			}
			break;
		} else {
L
Linus Torvalds 已提交
348
			c->cputype = CPU_R3000;
349 350
			__cpu_name[cpu] = "R3000";
		}
L
Linus Torvalds 已提交
351
		c->isa_level = MIPS_CPU_ISA_I;
R
Ralf Baechle 已提交
352 353
		c->options = MIPS_CPU_TLB | MIPS_CPU_3K_CACHE |
		             MIPS_CPU_NOFPUEX;
L
Linus Torvalds 已提交
354 355 356 357 358 359
		if (__cpu_has_fpu())
			c->options |= MIPS_CPU_FPU;
		c->tlbsize = 64;
		break;
	case PRID_IMP_R4000:
		if (read_c0_config() & CONF_SC) {
360
			if ((c->processor_id & 0xff) >= PRID_REV_R4400) {
L
Linus Torvalds 已提交
361
				c->cputype = CPU_R4400PC;
362 363
				__cpu_name[cpu] = "R4400PC";
			} else {
L
Linus Torvalds 已提交
364
				c->cputype = CPU_R4000PC;
365 366
				__cpu_name[cpu] = "R4000PC";
			}
L
Linus Torvalds 已提交
367
		} else {
368
			if ((c->processor_id & 0xff) >= PRID_REV_R4400) {
L
Linus Torvalds 已提交
369
				c->cputype = CPU_R4400SC;
370 371
				__cpu_name[cpu] = "R4400SC";
			} else {
L
Linus Torvalds 已提交
372
				c->cputype = CPU_R4000SC;
373 374
				__cpu_name[cpu] = "R4000SC";
			}
L
Linus Torvalds 已提交
375 376 377 378 379 380 381 382 383 384 385 386
		}

		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;
387
			__cpu_name[cpu] = "NEC VR4111";
L
Linus Torvalds 已提交
388 389 390
			break;
		case PRID_REV_VR4121:
			c->cputype = CPU_VR4121;
391
			__cpu_name[cpu] = "NEC VR4121";
L
Linus Torvalds 已提交
392 393
			break;
		case PRID_REV_VR4122:
394
			if ((c->processor_id & 0xf) < 0x3) {
L
Linus Torvalds 已提交
395
				c->cputype = CPU_VR4122;
396 397
				__cpu_name[cpu] = "NEC VR4122";
			} else {
L
Linus Torvalds 已提交
398
				c->cputype = CPU_VR4181A;
399 400
				__cpu_name[cpu] = "NEC VR4181A";
			}
L
Linus Torvalds 已提交
401 402
			break;
		case PRID_REV_VR4130:
403
			if ((c->processor_id & 0xf) < 0x4) {
L
Linus Torvalds 已提交
404
				c->cputype = CPU_VR4131;
405 406
				__cpu_name[cpu] = "NEC VR4131";
			} else {
L
Linus Torvalds 已提交
407
				c->cputype = CPU_VR4133;
408 409
				__cpu_name[cpu] = "NEC VR4133";
			}
L
Linus Torvalds 已提交
410 411 412 413
			break;
		default:
			printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n");
			c->cputype = CPU_VR41XX;
414
			__cpu_name[cpu] = "NEC Vr41xx";
L
Linus Torvalds 已提交
415 416 417 418 419 420 421 422
			break;
		}
		c->isa_level = MIPS_CPU_ISA_III;
		c->options = R4K_OPTS;
		c->tlbsize = 32;
		break;
	case PRID_IMP_R4300:
		c->cputype = CPU_R4300;
423
		__cpu_name[cpu] = "R4300";
L
Linus Torvalds 已提交
424 425 426 427 428 429 430
		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;
431
		__cpu_name[cpu] = "R4600";
L
Linus Torvalds 已提交
432
		c->isa_level = MIPS_CPU_ISA_III;
T
Thiemo Seufer 已提交
433 434
		c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
			     MIPS_CPU_LLSC;
L
Linus Torvalds 已提交
435 436 437 438 439 440 441 442 443 444
		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.
		 */
445
		c->cputype = CPU_R4650;
446
		__cpu_name[cpu] = "R4650";
L
Linus Torvalds 已提交
447 448 449 450 451 452 453
	 	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 已提交
454
		c->options = MIPS_CPU_TLB | MIPS_CPU_TX39_CACHE;
L
Linus Torvalds 已提交
455 456 457

		if ((c->processor_id & 0xf0) == (PRID_REV_TX3927 & 0xf0)) {
			c->cputype = CPU_TX3927;
458
			__cpu_name[cpu] = "TX3927";
L
Linus Torvalds 已提交
459 460 461 462 463
			c->tlbsize = 64;
		} else {
			switch (c->processor_id & 0xff) {
			case PRID_REV_TX3912:
				c->cputype = CPU_TX3912;
464
				__cpu_name[cpu] = "TX3912";
L
Linus Torvalds 已提交
465 466 467 468
				c->tlbsize = 32;
				break;
			case PRID_REV_TX3922:
				c->cputype = CPU_TX3922;
469
				__cpu_name[cpu] = "TX3922";
L
Linus Torvalds 已提交
470 471 472 473 474 475 476
				c->tlbsize = 64;
				break;
			}
		}
		break;
	case PRID_IMP_R4700:
		c->cputype = CPU_R4700;
477
		__cpu_name[cpu] = "R4700";
L
Linus Torvalds 已提交
478 479 480 481 482 483 484
		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;
485
		__cpu_name[cpu] = "R49XX";
L
Linus Torvalds 已提交
486 487 488 489 490 491 492 493
		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;
494
		__cpu_name[cpu] = "R5000";
L
Linus Torvalds 已提交
495 496 497 498 499 500 501
		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;
502
		__cpu_name[cpu] = "R5432";
L
Linus Torvalds 已提交
503 504 505 506 507 508 509
		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;
510
		__cpu_name[cpu] = "R5500";
L
Linus Torvalds 已提交
511 512 513 514 515 516 517
		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;
518
		__cpu_name[cpu] = "Nevada";
L
Linus Torvalds 已提交
519 520 521 522 523 524 525
		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;
526
		__cpu_name[cpu] = "R6000";
L
Linus Torvalds 已提交
527 528 529 530 531 532 533
		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;
534
		__cpu_name[cpu] = "R6000A";
L
Linus Torvalds 已提交
535 536 537 538 539 540 541
		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;
542
		__cpu_name[cpu] = "RM7000";
L
Linus Torvalds 已提交
543 544 545 546 547 548 549 550 551 552 553 554 555 556 557
		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;
558
		__cpu_name[cpu] = "RM9000";
L
Linus Torvalds 已提交
559 560 561 562 563 564 565 566 567 568 569 570 571 572
		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;
573
		__cpu_name[cpu] = "RM8000";
L
Linus Torvalds 已提交
574 575 576 577 578 579 580 581
		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;
582
		__cpu_name[cpu] = "R10000";
L
Linus Torvalds 已提交
583
		c->isa_level = MIPS_CPU_ISA_IV;
584
		c->options = MIPS_CPU_TLB | MIPS_CPU_4K_CACHE | MIPS_CPU_4KEX |
L
Linus Torvalds 已提交
585 586 587 588 589 590 591
		             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;
592
		__cpu_name[cpu] = "R12000";
L
Linus Torvalds 已提交
593
		c->isa_level = MIPS_CPU_ISA_IV;
594
		c->options = MIPS_CPU_TLB | MIPS_CPU_4K_CACHE | MIPS_CPU_4KEX |
L
Linus Torvalds 已提交
595 596 597 598 599
		             MIPS_CPU_FPU | MIPS_CPU_32FPR |
			     MIPS_CPU_COUNTER | MIPS_CPU_WATCH |
		             MIPS_CPU_LLSC;
		c->tlbsize = 64;
		break;
K
Kumba 已提交
600 601
	case PRID_IMP_R14000:
		c->cputype = CPU_R14000;
602
		__cpu_name[cpu] = "R14000";
K
Kumba 已提交
603 604 605 606 607 608 609
		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;
610 611
	case PRID_IMP_LOONGSON2:
		c->cputype = CPU_LOONGSON2;
612
		__cpu_name[cpu] = "ICT Loongson-2";
613 614 615 616 617 618
		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 已提交
619 620 621
	}
}

622
static char unknown_isa[] __cpuinitdata = KERN_ERR \
623 624
	"Unsupported ISA type, c0.config0: %d.";

625
static inline unsigned int decode_config0(struct cpuinfo_mips *c)
L
Linus Torvalds 已提交
626
{
627 628
	unsigned int config0;
	int isa;
L
Linus Torvalds 已提交
629

630 631 632
	config0 = read_c0_config();

	if (((config0 & MIPS_CONF_MT) >> 7) == 1)
R
Ralf Baechle 已提交
633
		c->options |= MIPS_CPU_TLB;
634 635 636
	isa = (config0 & MIPS_CONF_AT) >> 13;
	switch (isa) {
	case 0:
637
		switch ((config0 & MIPS_CONF_AR) >> 10) {
638 639 640 641 642 643 644 645 646
		case 0:
			c->isa_level = MIPS_CPU_ISA_M32R1;
			break;
		case 1:
			c->isa_level = MIPS_CPU_ISA_M32R2;
			break;
		default:
			goto unknown;
		}
647 648
		break;
	case 2:
649
		switch ((config0 & MIPS_CONF_AR) >> 10) {
650 651 652 653 654 655 656 657 658
		case 0:
			c->isa_level = MIPS_CPU_ISA_M64R1;
			break;
		case 1:
			c->isa_level = MIPS_CPU_ISA_M64R2;
			break;
		default:
			goto unknown;
		}
659 660
		break;
	default:
661
		goto unknown;
662 663 664
	}

	return config0 & MIPS_CONF_M;
665 666 667

unknown:
	panic(unknown_isa, config0);
668 669 670 671 672
}

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

	config1 = read_c0_config1();
675 676 677 678

	if (config1 & MIPS_CONF1_MD)
		c->ases |= MIPS_ASE_MDMX;
	if (config1 & MIPS_CONF1_WR)
L
Linus Torvalds 已提交
679
		c->options |= MIPS_CPU_WATCH;
680 681 682
	if (config1 & MIPS_CONF1_CA)
		c->ases |= MIPS_ASE_MIPS16;
	if (config1 & MIPS_CONF1_EP)
L
Linus Torvalds 已提交
683
		c->options |= MIPS_CPU_EJTAG;
684
	if (config1 & MIPS_CONF1_FP) {
L
Linus Torvalds 已提交
685 686 687
		c->options |= MIPS_CPU_FPU;
		c->options |= MIPS_CPU_32FPR;
	}
688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713
	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;
714 715
	if (config3 & MIPS_CONF3_DSP)
		c->ases |= MIPS_ASE_DSP;
716 717 718 719 720
	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 已提交
721
	        c->ases |= MIPS_ASE_MIPSMT;
722 723
	if (config3 & MIPS_CONF3_ULRI)
		c->options |= MIPS_CPU_ULRI;
724 725 726 727

	return config3 & MIPS_CONF_M;
}

728 729 730 731 732 733 734 735 736 737 738 739 740
static inline unsigned int decode_config4(struct cpuinfo_mips *c)
{
	unsigned int config4;

	config4 = read_c0_config4();

	if ((config4 & MIPS_CONF4_MMUEXTDEF) == MIPS_CONF4_MMUEXTDEF_MMUSIZEEXT
	    && cpu_has_tlb)
		c->tlbsize += (config4 & MIPS_CONF4_MMUSIZEEXT) * 0x40;

	return config4 & MIPS_CONF_M;
}

741
static void __cpuinit decode_configs(struct cpuinfo_mips *c)
742
{
743 744
	int ok;

745
	/* MIPS32 or MIPS64 compliant CPU.  */
R
Ralf Baechle 已提交
746 747
	c->options = MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE | MIPS_CPU_COUNTER |
	             MIPS_CPU_DIVEC | MIPS_CPU_LLSC | MIPS_CPU_MCHECK;
748

L
Linus Torvalds 已提交
749 750
	c->scache.flags = MIPS_CACHE_NOT_PRESENT;

751 752 753 754 755 756 757 758
	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);
759 760
	if (ok)
		ok = decode_config4(c);
761 762

	mips_probe_watch_registers(c);
L
Linus Torvalds 已提交
763 764
}

765
static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu)
L
Linus Torvalds 已提交
766
{
767
	decode_configs(c);
L
Linus Torvalds 已提交
768 769 770
	switch (c->processor_id & 0xff00) {
	case PRID_IMP_4KC:
		c->cputype = CPU_4KC;
771
		__cpu_name[cpu] = "MIPS 4Kc";
L
Linus Torvalds 已提交
772 773
		break;
	case PRID_IMP_4KEC:
774 775
	case PRID_IMP_4KECR2:
		c->cputype = CPU_4KEC;
776
		__cpu_name[cpu] = "MIPS 4KEc";
777
		break;
L
Linus Torvalds 已提交
778
	case PRID_IMP_4KSC:
R
Ralf Baechle 已提交
779
	case PRID_IMP_4KSD:
L
Linus Torvalds 已提交
780
		c->cputype = CPU_4KSC;
781
		__cpu_name[cpu] = "MIPS 4KSc";
L
Linus Torvalds 已提交
782 783 784
		break;
	case PRID_IMP_5KC:
		c->cputype = CPU_5KC;
785
		__cpu_name[cpu] = "MIPS 5Kc";
L
Linus Torvalds 已提交
786 787 788
		break;
	case PRID_IMP_20KC:
		c->cputype = CPU_20KC;
789
		__cpu_name[cpu] = "MIPS 20Kc";
L
Linus Torvalds 已提交
790 791
		break;
	case PRID_IMP_24K:
792
	case PRID_IMP_24KE:
L
Linus Torvalds 已提交
793
		c->cputype = CPU_24K;
794
		__cpu_name[cpu] = "MIPS 24Kc";
L
Linus Torvalds 已提交
795 796 797
		break;
	case PRID_IMP_25KF:
		c->cputype = CPU_25KF;
798
		__cpu_name[cpu] = "MIPS 25Kc";
L
Linus Torvalds 已提交
799
		break;
R
Ralf Baechle 已提交
800 801
	case PRID_IMP_34K:
		c->cputype = CPU_34K;
802
		__cpu_name[cpu] = "MIPS 34Kc";
R
Ralf Baechle 已提交
803
		break;
804 805
	case PRID_IMP_74K:
		c->cputype = CPU_74K;
806
		__cpu_name[cpu] = "MIPS 74Kc";
807
		break;
808 809
	case PRID_IMP_1004K:
		c->cputype = CPU_1004K;
810
		__cpu_name[cpu] = "MIPS 1004Kc";
811
		break;
L
Linus Torvalds 已提交
812
	}
C
Chris Dearman 已提交
813 814

	spram_config();
L
Linus Torvalds 已提交
815 816
}

817
static inline void cpu_probe_alchemy(struct cpuinfo_mips *c, unsigned int cpu)
L
Linus Torvalds 已提交
818
{
819
	decode_configs(c);
L
Linus Torvalds 已提交
820 821 822
	switch (c->processor_id & 0xff00) {
	case PRID_IMP_AU1_REV1:
	case PRID_IMP_AU1_REV2:
823
		c->cputype = CPU_ALCHEMY;
L
Linus Torvalds 已提交
824 825
		switch ((c->processor_id >> 24) & 0xff) {
		case 0:
826
			__cpu_name[cpu] = "Au1000";
L
Linus Torvalds 已提交
827 828
			break;
		case 1:
829
			__cpu_name[cpu] = "Au1500";
L
Linus Torvalds 已提交
830 831
			break;
		case 2:
832
			__cpu_name[cpu] = "Au1100";
L
Linus Torvalds 已提交
833 834
			break;
		case 3:
835
			__cpu_name[cpu] = "Au1550";
L
Linus Torvalds 已提交
836
			break;
P
Pete Popov 已提交
837
		case 4:
838
			__cpu_name[cpu] = "Au1200";
839
			if ((c->processor_id & 0xff) == 2)
840
				__cpu_name[cpu] = "Au1250";
841 842
			break;
		case 5:
843
			__cpu_name[cpu] = "Au1210";
P
Pete Popov 已提交
844
			break;
L
Linus Torvalds 已提交
845
		default:
846
			__cpu_name[cpu] = "Au1xxx";
L
Linus Torvalds 已提交
847 848 849 850 851 852
			break;
		}
		break;
	}
}

853
static inline void cpu_probe_sibyte(struct cpuinfo_mips *c, unsigned int cpu)
L
Linus Torvalds 已提交
854
{
855
	decode_configs(c);
R
Ralf Baechle 已提交
856

L
Linus Torvalds 已提交
857 858 859
	switch (c->processor_id & 0xff00) {
	case PRID_IMP_SB1:
		c->cputype = CPU_SB1;
860
		__cpu_name[cpu] = "SiByte SB1";
L
Linus Torvalds 已提交
861
		/* FPU in pass1 is known to have issues. */
862
		if ((c->processor_id & 0xff) < 0x02)
863
			c->options &= ~(MIPS_CPU_FPU | MIPS_CPU_32FPR);
L
Linus Torvalds 已提交
864
		break;
A
Andrew Isaacson 已提交
865 866
	case PRID_IMP_SB1A:
		c->cputype = CPU_SB1A;
867
		__cpu_name[cpu] = "SiByte SB1A";
A
Andrew Isaacson 已提交
868
		break;
L
Linus Torvalds 已提交
869 870 871
	}
}

872
static inline void cpu_probe_sandcraft(struct cpuinfo_mips *c, unsigned int cpu)
L
Linus Torvalds 已提交
873
{
874
	decode_configs(c);
L
Linus Torvalds 已提交
875 876 877
	switch (c->processor_id & 0xff00) {
	case PRID_IMP_SR71000:
		c->cputype = CPU_SR71000;
878
		__cpu_name[cpu] = "Sandcraft SR71000";
L
Linus Torvalds 已提交
879 880 881 882 883 884
		c->scache.ways = 8;
		c->tlbsize = 64;
		break;
	}
}

885
static inline void cpu_probe_nxp(struct cpuinfo_mips *c, unsigned int cpu)
886 887 888 889 890
{
	decode_configs(c);
	switch (c->processor_id & 0xff00) {
	case PRID_IMP_PR4450:
		c->cputype = CPU_PR4450;
891
		__cpu_name[cpu] = "Philips PR4450";
892
		c->isa_level = MIPS_CPU_ISA_M32R1;
893 894 895 896
		break;
	}
}

897
static inline void cpu_probe_broadcom(struct cpuinfo_mips *c, unsigned int cpu)
898 899 900 901
{
	decode_configs(c);
	switch (c->processor_id & 0xff00) {
	case PRID_IMP_BCM3302:
902
	 /* same as PRID_IMP_BCM6338 */
903
		c->cputype = CPU_BCM3302;
904
		__cpu_name[cpu] = "Broadcom BCM3302";
905 906 907
		break;
	case PRID_IMP_BCM4710:
		c->cputype = CPU_BCM4710;
908
		__cpu_name[cpu] = "Broadcom BCM4710";
909
		break;
910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928
	case PRID_IMP_BCM6345:
		c->cputype = CPU_BCM6345;
		__cpu_name[cpu] = "Broadcom BCM6345";
		break;
	case PRID_IMP_BCM6348:
		c->cputype = CPU_BCM6348;
		__cpu_name[cpu] = "Broadcom BCM6348";
		break;
	case PRID_IMP_BCM4350:
		switch (c->processor_id & 0xf0) {
		case PRID_REV_BCM6358:
			c->cputype = CPU_BCM6358;
			__cpu_name[cpu] = "Broadcom BCM6358";
			break;
		default:
			c->cputype = CPU_UNKNOWN;
			break;
		}
		break;
929 930 931
	}
}

932 933 934 935 936 937 938
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:
939 940 941
		c->cputype = CPU_CAVIUM_OCTEON;
		__cpu_name[cpu] = "Cavium Octeon";
		goto platform;
942 943 944 945
	case PRID_IMP_CAVIUM_CN58XX:
	case PRID_IMP_CAVIUM_CN56XX:
	case PRID_IMP_CAVIUM_CN50XX:
	case PRID_IMP_CAVIUM_CN52XX:
946 947 948
		c->cputype = CPU_CAVIUM_OCTEON_PLUS;
		__cpu_name[cpu] = "Cavium Octeon+";
platform:
949 950
		if (cpu == 0)
			__elf_platform = "octeon";
951 952 953 954 955 956 957 958
		break;
	default:
		printk(KERN_INFO "Unknown Octeon chip!\n");
		c->cputype = CPU_UNKNOWN;
		break;
	}
}

959
const char *__cpu_name[NR_CPUS];
960
const char *__elf_platform;
961

962
__cpuinit void cpu_probe(void)
L
Linus Torvalds 已提交
963 964
{
	struct cpuinfo_mips *c = &current_cpu_data;
965
	unsigned int cpu = smp_processor_id();
L
Linus Torvalds 已提交
966 967 968 969 970 971 972 973

	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:
974
		cpu_probe_legacy(c, cpu);
L
Linus Torvalds 已提交
975 976
		break;
	case PRID_COMP_MIPS:
977
		cpu_probe_mips(c, cpu);
L
Linus Torvalds 已提交
978 979
		break;
	case PRID_COMP_ALCHEMY:
980
		cpu_probe_alchemy(c, cpu);
L
Linus Torvalds 已提交
981 982
		break;
	case PRID_COMP_SIBYTE:
983
		cpu_probe_sibyte(c, cpu);
L
Linus Torvalds 已提交
984
		break;
985
	case PRID_COMP_BROADCOM:
986
		cpu_probe_broadcom(c, cpu);
987
		break;
L
Linus Torvalds 已提交
988
	case PRID_COMP_SANDCRAFT:
989
		cpu_probe_sandcraft(c, cpu);
L
Linus Torvalds 已提交
990
		break;
991
	case PRID_COMP_NXP:
992
		cpu_probe_nxp(c, cpu);
993
		break;
994 995 996
	case PRID_COMP_CAVIUM:
		cpu_probe_cavium(c, cpu);
		break;
L
Linus Torvalds 已提交
997
	}
998

999 1000 1001
	BUG_ON(!__cpu_name[cpu]);
	BUG_ON(c->cputype == CPU_UNKNOWN);

1002 1003 1004 1005 1006 1007 1008
	/*
	 * 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);

1009 1010 1011 1012 1013 1014
	if (mips_fpu_disabled)
		c->options &= ~MIPS_CPU_FPU;

	if (mips_dsp_disabled)
		c->ases &= ~MIPS_ASE_DSP;

1015
	if (c->options & MIPS_CPU_FPU) {
L
Linus Torvalds 已提交
1016
		c->fpu_id = cpu_get_fpu_id();
1017

1018
		if (c->isa_level == MIPS_CPU_ISA_M32R1 ||
1019 1020 1021
		    c->isa_level == MIPS_CPU_ISA_M32R2 ||
		    c->isa_level == MIPS_CPU_ISA_M64R1 ||
		    c->isa_level == MIPS_CPU_ISA_M64R2) {
1022 1023 1024 1025
			if (c->fpu_id & MIPS_FPIR_3D)
				c->ases |= MIPS_ASE_MIPS3D;
		}
	}
1026

R
Ralf Baechle 已提交
1027 1028 1029 1030
	if (cpu_has_mips_r2)
		c->srsets = ((read_c0_srsctl() >> 26) & 0x0f) + 1;
	else
		c->srsets = 1;
1031 1032

	cpu_probe_vmbits(c);
L
Linus Torvalds 已提交
1033 1034
}

1035
__cpuinit void cpu_report(void)
L
Linus Torvalds 已提交
1036 1037 1038
{
	struct cpuinfo_mips *c = &current_cpu_data;

1039 1040
	printk(KERN_INFO "CPU revision is: %08x (%s)\n",
	       c->processor_id, cpu_name_string());
L
Linus Torvalds 已提交
1041
	if (c->options & MIPS_CPU_FPU)
1042
		printk(KERN_INFO "FPU revision is: %08x\n", c->fpu_id);
L
Linus Torvalds 已提交
1043
}