diff mbox series

[V3,Resend] MIPS: Loongson: Add board_ebase_setup() support

Message ID 1584006117-28985-1-git-send-email-chenhc@lemote.com (mailing list archive)
State New
Headers show
Series [V3,Resend] MIPS: Loongson: Add board_ebase_setup() support | expand

Commit Message

Huacai Chen March 12, 2020, 9:41 a.m. UTC
The EBase registers of old Loongson processor models before 3A2000 are
32bit and have no WG bit; those of newer models are 64bit and do have
the WG bit.

Unfortunately, dynamically allocated EBase addresses do not work well
for the Loongson platform, because Loongson's memory layout is very
limited below 0x20000000. The dynamically allocated EBase address above
0x20000000 is thus unmappable to a KSEG0/KSEG1 virtual address, but the
cache error handler MUST be in KSEG1 (please see set_uncached_handler()
in traps.c).

Some might suggest that the cache error handler is hardly used so this
is not a problem, but Loongson's MMIO configuration registers might be
corrupted by set_uncached_handler().

To make Linux kernel on Loongson more robust, a board_ebase_setup() hook
is added to ensure CKSEG0 is always used for EBase. This is also useful
for configurations where firmware-provided EBase is not sane.

Maybe this problem is present for all MIPSr2 processors, but it seems
not all platforms have memory at physical address 0. So this patch only
touches Loongson.

Signed-off-by: Huacai Chen <chenhc@lemote.com>
---
 arch/mips/loongson64/init.c | 11 +++++++++++
 1 file changed, 11 insertions(+)
diff mbox series

Patch

diff --git a/arch/mips/loongson64/init.c b/arch/mips/loongson64/init.c
index 5ac1a0f..b8e54e1 100644
--- a/arch/mips/loongson64/init.c
+++ b/arch/mips/loongson64/init.c
@@ -13,6 +13,16 @@ 
 
 #include <loongson.h>
 
+static void __init mips_ebase_setup(void)
+{
+	ebase = CKSEG0;
+
+	if (cpu_has_ebase_wg)
+		write_c0_ebase(ebase | MIPS_EBASE_WG);
+
+	write_c0_ebase(ebase);
+}
+
 static void __init mips_nmi_setup(void)
 {
 	void *base;
@@ -38,6 +48,7 @@  void __init prom_init(void)
 	setup_8250_early_printk_port(TO_UNCAC(LOONGSON_REG_BASE + 0x1e0), 0, 1024);
 
 	register_smp_ops(&loongson3_smp_ops);
+	board_ebase_setup = mips_ebase_setup;
 	board_nmi_handler_setup = mips_nmi_setup;
 }