Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

MIPS: Tell R4k SC and MC variations apart

There is no reliable way to tell R4000/R4400 SC and MC variations apart,
however simple heuristic should give good results. Only the MC version
supports coherent caching so we can rely on such a mode having been set
for KSEG0 by the power-on firmware to reliably indicate an MC processor.
SC processors reportedly hang on coherent cached memory accesses and Linux
is linked to a cached load address so the firmware has to use the correct
caching mode to download the kernel image in a cached mode successfully.

OTOH if the firmware chooses to use either the non-coherent cached or the
uncached mode for KSEG0 on an MC processor, then the SC variant will be
reported, just as we currently do, so no regression here.

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
Cc: Jonas Gorski <jogo@openwrt.org>
Cc: MIPS Mailing List <linux-mips@linux-mips.org>
Patchwork: https://patchwork.linux-mips.org/patch/5882/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

authored by

Maciej W. Rozycki and committed by
Ralf Baechle
7f177a52 33afab80

+24 -4
+24 -4
arch/mips/kernel/cpu-probe.c
··· 376 376 __cpu_name[cpu] = "R4000PC"; 377 377 } 378 378 } else { 379 + int cca = read_c0_config() & CONF_CM_CMASK; 380 + int mc; 381 + 382 + /* 383 + * SC and MC versions can't be reliably told apart, 384 + * but only the latter support coherent caching 385 + * modes so assume the firmware has set the KSEG0 386 + * coherency attribute reasonably (if uncached, we 387 + * assume SC). 388 + */ 389 + switch (cca) { 390 + case CONF_CM_CACHABLE_CE: 391 + case CONF_CM_CACHABLE_COW: 392 + case CONF_CM_CACHABLE_CUW: 393 + mc = 1; 394 + break; 395 + default: 396 + mc = 0; 397 + break; 398 + } 379 399 if ((c->processor_id & PRID_REV_MASK) >= 380 400 PRID_REV_R4400) { 381 - c->cputype = CPU_R4400SC; 382 - __cpu_name[cpu] = "R4400SC"; 401 + c->cputype = mc ? CPU_R4400MC : CPU_R4400SC; 402 + __cpu_name[cpu] = mc ? "R4400MC" : "R4400SC"; 383 403 } else { 384 - c->cputype = CPU_R4000SC; 385 - __cpu_name[cpu] = "R4000SC"; 404 + c->cputype = mc ? CPU_R4000MC : CPU_R4000SC; 405 + __cpu_name[cpu] = mc ? "R4000MC" : "R4000SC"; 386 406 } 387 407 } 388 408