mips: vcoreiii: Fix cache coherency issues
authorLars Povlsen <lars.povlsen@microchip.com>
Thu, 6 Feb 2020 09:45:40 +0000 (10:45 +0100)
committerDaniel Schwierzeck <daniel.schwierzeck@gmail.com>
Thu, 9 Apr 2020 16:55:59 +0000 (18:55 +0200)
This patch fixes an stability issue seen on some vcoreiii targets,
which was root caused to a cache inconsistency situation.

The inconsistency was caused by having kuseg pointing to NOR area but
used as a stack/gd/heap area during initialization, while only
relatively late remapping the RAM area into kuseg position.

The fix is to initialize the DDR right after the TLB setup, and then
remapping it into position before gd/stack/heap usage.

Reported-by: Ramin Seyed-Moussavi <ramin.moussavi@yacoub.de>
Reviewed-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Reviewed-by: Horatiu Vultur <horatiu.vultur@microchip.com>
Signed-off-by: Lars Povlsen <lars.povlsen@microchip.com>
arch/mips/mach-mscc/cpu.c
arch/mips/mach-mscc/dram.c
arch/mips/mach-mscc/include/mach/ddr.h
arch/mips/mach-mscc/lowlevel_init.S

index ac75d51da5fb2ec07ae686b28535a213cb98d41e..3ee589891b1af035f2f7a63791af55757448991c 100644 (file)
@@ -7,6 +7,7 @@
 
 #include <asm/io.h>
 #include <asm/types.h>
+#include <asm/mipsregs.h>
 
 #include <mach/tlb.h>
 #include <mach/ddr.h>
@@ -53,7 +54,6 @@ void vcoreiii_tlb_init(void)
                   MMU_REGIO_RW);
 #endif
 
-#if  CONFIG_SYS_TEXT_BASE == MSCC_FLASH_TO
        /*
         * If U-Boot is located in NOR then we want to be able to use
         * the data cache in order to boot in a decent duration
@@ -71,9 +71,10 @@ void vcoreiii_tlb_init(void)
        create_tlb(tlbix++, MSCC_DDR_TO, MSCC_RAM_TLB_SIZE, MMU_REGIO_RW,
                   MSCC_ATTRIB2);
 
-       /* Enable caches by clearing the bit ERL, which is set on reset */
-       write_c0_status(read_c0_status() & ~BIT(2));
-#endif /* CONFIG_SYS_TEXT_BASE */
+       /* Enable mapping (using TLB) kuseg by clearing the bit ERL,
+        * which is set on reset.
+        */
+       write_c0_status(read_c0_status() & ~ST0_ERL);
 }
 
 int mach_cpu_init(void)
index c43f7a585bf8a51f9bb7870919f88fd401891c5f..72c70c9e8432f36c6d23a5cc5ce88d29f9faaed5 100644 (file)
@@ -31,7 +31,7 @@ static inline int vcoreiii_train_bytelane(void)
 
 int vcoreiii_ddr_init(void)
 {
-       int res;
+       register int res;
 
        if (!(readl(BASE_CFG + ICPU_MEMCTRL_STAT)
              & ICPU_MEMCTRL_STAT_INIT_DONE)) {
@@ -40,20 +40,19 @@ int vcoreiii_ddr_init(void)
                if (hal_vcoreiii_init_dqs() || vcoreiii_train_bytelane())
                        hal_vcoreiii_ddr_failed();
        }
-#if (CONFIG_SYS_TEXT_BASE != 0x20000000)
+
        res = dram_check();
        if (res == 0)
                hal_vcoreiii_ddr_verified();
        else
                hal_vcoreiii_ddr_failed();
 
-       /* Clear boot-mode and read-back to activate/verify */
+       /*  Remap DDR to kuseg: Clear boot-mode */
        clrbits_le32(BASE_CFG + ICPU_GENERAL_CTRL,
                     ICPU_GENERAL_CTRL_BOOT_MODE_ENA);
+       /* - and read-back to activate/verify */
        readl(BASE_CFG + ICPU_GENERAL_CTRL);
-#else
-       res = 0;
-#endif
+
        return res;
 }
 
@@ -66,9 +65,6 @@ int print_cpuinfo(void)
 
 int dram_init(void)
 {
-       while (vcoreiii_ddr_init())
-               ;
-
        gd->ram_size = CONFIG_SYS_SDRAM_SIZE;
        return 0;
 }
index d1f4287f654661727bba043984843c5c697002f8..bf75e52ec3c652a45b9f6d685a703904f9bba579 100644 (file)
@@ -435,16 +435,12 @@ static inline void hal_vcoreiii_ddr_failed(void)
        reset = KSEG0ADDR(_machine_restart);
        icache_lock((void *)reset, 128);
        asm volatile ("jr %0"::"r" (reset));
-
-       panic("DDR init failed\n");
 }
 #else                          /* JR2 || ServalT */
 static inline void hal_vcoreiii_ddr_failed(void)
 {
        writel(0, BASE_CFG + ICPU_RESET);
        writel(PERF_SOFT_RST_SOFT_CHIP_RST, BASE_CFG + PERF_SOFT_RST);
-
-       panic("DDR init failed\n");
 }
 #endif
 
index dfbe06766cde82da55aaa305f5740ae5ebc0e528..91f29ae252cc55308f1c0a3dec32fcb08131e617 100644 (file)
@@ -8,6 +8,7 @@
 
     .set noreorder
     .extern     vcoreiii_tlb_init
+    .extern     vcoreiii_ddr_init
 #ifdef CONFIG_SOC_LUTON
     .extern     pll_init
 #endif
@@ -17,14 +18,28 @@ LEAF(lowlevel_init)
         * As we have no stack yet, we can assume the restricted
         * luxury of the sX-registers without saving them
         */
-       move    s0,ra
+
+       /* Modify ra/s0 such we return to physical NOR location */
+       li      t0, 0x0fffffff
+       li      t1, CONFIG_SYS_TEXT_BASE
+       and     s0, ra, t0
+       add     s0, s0, t1
 
        jal     vcoreiii_tlb_init
         nop
+
 #ifdef CONFIG_SOC_LUTON
        jal     pll_init
         nop
 #endif
+
+       /* Initialize DDR controller to enable stack/gd/heap */
+0:
+       jal     vcoreiii_ddr_init
+        nop
+       bnez    v0, 0b          /* Retry on error */
+        nop
+
        jr      s0
         nop
        END(lowlevel_init)