R5k CPUs have a bug, where ll access to XKPHYS addresses don't work.
Check for this bug and enable workaround, if possible.
Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
---
arch/mips/kernel/cpu-bugs64.c | 36 ++++++++++++++++++++++++++++++++++++
1 files changed, 36 insertions(+), 0 deletions(-)
diff --git a/arch/mips/kernel/cpu-bugs64.c b/arch/mips/kernel/cpu-bugs64.c
index 02b7713..8e55649 100644
--- a/arch/mips/kernel/cpu-bugs64.c
+++ b/arch/mips/kernel/cpu-bugs64.c
@@ -26,6 +26,8 @@ static char r4kwar[] __initdata =
"Enable CPU_R4000_WORKAROUNDS to rectify.";
static char daddiwar[] __initdata =
"Enable CPU_DADDI_WORKAROUNDS to rectify.";
+static char xkphysllwar[] __initdata =
+ "CPU has ll xkphys bug.";
static inline void align_mod(const int align, const int mod)
{
@@ -307,10 +309,44 @@ static inline void check_daddiu(void)
panic(bug64hit, !DADDI_WAR ? daddiwar : nowar);
}
+static u32 ll(u32 *p)
+{
+ u32 ret;
+
+ asm volatile(
+ "ll %0, %1\n\t"
+ : "=&r" (ret)
+ : "m" (*p));
+
+ return ret;
+}
+
+void __init check_ll_xkphys(void)
+{
+ static u32 val;
+ u32 *p = (u32 *)PHYS_TO_XKPHYS(K_CALG_NONCOHERENT,
+ CPHYSADDR((unsigned long)&val));
+
+ printk("Checking for the ll/lld xkphys bug... ");
+ memset(p, 0xff, sizeof(val));
+ if (ll(p) != 0xffffffff) {
+ printk("yes, enabling workaround... ");
+ cpu_data[0].options &= ~MIPS_CPU_LLSC;
+ if (cpu_has_llsc != (cpu_data[0].options & MIPS_CPU_LLSC)) {
+ printk("failed.\n");
+ panic(bug64hit, xkphysllwar);
+ }
+ printk("ok.\n");
+ } else
+ printk("no.\n");
+}
+
+
void __init check_bugs64_early(void)
{
check_mult_sh();
check_daddiu();
+ check_ll_xkphys();
}
void __init check_bugs64(void)
|