Commit 7f177a52 authored by Maciej W. Rozycki's avatar Maciej W. Rozycki Committed by Ralf Baechle

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: default avatarMaciej 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: default avatarRalf Baechle <ralf@linux-mips.org>
parent 33afab80
...@@ -376,13 +376,33 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) ...@@ -376,13 +376,33 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
__cpu_name[cpu] = "R4000PC"; __cpu_name[cpu] = "R4000PC";
} }
} else { } else {
int cca = read_c0_config() & CONF_CM_CMASK;
int mc;
/*
* SC and MC versions can't be reliably told apart,
* but only the latter support coherent caching
* modes so assume the firmware has set the KSEG0
* coherency attribute reasonably (if uncached, we
* assume SC).
*/
switch (cca) {
case CONF_CM_CACHABLE_CE:
case CONF_CM_CACHABLE_COW:
case CONF_CM_CACHABLE_CUW:
mc = 1;
break;
default:
mc = 0;
break;
}
if ((c->processor_id & PRID_REV_MASK) >= if ((c->processor_id & PRID_REV_MASK) >=
PRID_REV_R4400) { PRID_REV_R4400) {
c->cputype = CPU_R4400SC; c->cputype = mc ? CPU_R4400MC : CPU_R4400SC;
__cpu_name[cpu] = "R4400SC"; __cpu_name[cpu] = mc ? "R4400MC" : "R4400SC";
} else { } else {
c->cputype = CPU_R4000SC; c->cputype = mc ? CPU_R4000MC : CPU_R4000SC;
__cpu_name[cpu] = "R4000SC"; __cpu_name[cpu] = mc ? "R4000MC" : "R4000SC";
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment