Enable MMU and caches very early on in the boot process on i.MX8M
in U-Boot proper. This allows board_init_f to run with icache and
dcache enabled, which saves some 700 milliseconds of boot time on
i.MX8M Plus based device.

The 'bootstage report' output is below:

Before:
```
Timer summary in microseconds (8 records):
       Mark    Elapsed  Stage
          0          0  reset
    961,363    961,363  board_init_f
  1,818,874    857,511  board_init_r
  1,921,474    102,600  eth_common_init
  2,013,702     92,228  eth_initialize
  2,015,238      1,536  main_loop

Accumulated time:
                32,775  dm_r
               289,165  dm_f
```

After:
```
Timer summary in microseconds (8 records):
       Mark    Elapsed  Stage
          0          0  reset
    989,466    989,466  board_init_f
  1,179,100    189,634  board_init_r
  1,281,456    102,356  eth_common_init
  1,373,857     92,401  eth_initialize
  1,375,396      1,539  main_loop

Accumulated time:
                12,630  dm_f
                32,635  dm_r
```

Signed-off-by: Marek Vasut <[email protected]>
---
Cc: "NXP i.MX U-Boot Team" <[email protected]>
Cc: Fabio Estevam <[email protected]>
Cc: Peng Fan <[email protected]>
Cc: Stefano Babic <[email protected]>
Cc: Tom Rini <[email protected]>
Cc: [email protected]
---
 arch/arm/mach-imx/imx8m/soc.c | 46 +++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/arch/arm/mach-imx/imx8m/soc.c b/arch/arm/mach-imx/imx8m/soc.c
index be38ca52885..7ac26d501ac 100644
--- a/arch/arm/mach-imx/imx8m/soc.c
+++ b/arch/arm/mach-imx/imx8m/soc.c
@@ -206,6 +206,14 @@ void enable_caches(void)
        int entry = imx8m_find_dram_entry_in_mem_map();
        u64 attrs = imx8m_mem_map[entry].attrs;
 
+       /* Deactivate the data cache, possibly enabled in arch_cpu_init() */
+       dcache_disable();
+       /*
+        * Force the call of setup_all_pgtables() in mmu_setup() by clearing 
tlb_fillptr
+        * to update the TLB location udpated in board_f.c::reserve_mmu
+        */
+       gd->arch.tlb_fillptr = 0;
+
        while (i < CONFIG_NR_DRAM_BANKS &&
               entry < ARRAY_SIZE(imx8m_mem_map)) {
                if (gd->bd->bi_dram[i].start == 0)
@@ -587,12 +595,50 @@ static void imx8m_setup_csu_tzasc(void)
        }
 }
 
+/*
+ * Place early TLB into the .data section so that it will not
+ * get cleared, use 16 kiB alignment.
+ */
+#define EARLY_TLB_SIZE SZ_64K
+u8 early_tlb[EARLY_TLB_SIZE] __section(".data") __aligned(0x4000);
+
+/*
+ * Initialize the MMU and activate cache in U-Boot pre-reloc stage
+ * MMU/TLB is updated in enable_caches() for U-Boot after relocation
+ */
+static void early_enable_caches(void)
+{
+       phys_size_t sdram_size;
+       int entry, ret;
+
+       if (IS_ENABLED(CONFIG_SPL_BUILD))
+               return;
+
+       if (CONFIG_IS_ENABLED(SYS_ICACHE_OFF) || 
CONFIG_IS_ENABLED(SYS_DCACHE_OFF))
+               return;
+
+       /* Use maximum available DRAM size in first bank. */
+       ret = board_phys_sdram_size(&sdram_size);
+       if (ret)
+               return;
+
+       entry = imx8m_find_dram_entry_in_mem_map();
+       imx8m_mem_map[entry].size = max(sdram_size, (phys_size_t)0xc0000000);
+
+       gd->arch.tlb_size = EARLY_TLB_SIZE;
+       gd->arch.tlb_addr = (unsigned long)&early_tlb;
+
+       /* Enable MMU (default configuration) */
+       dcache_enable();
+}
+
 int arch_cpu_init(void)
 {
        struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
 
 #if !CONFIG_IS_ENABLED(SYS_ICACHE_OFF)
        icache_enable();
+       early_enable_caches();
 #endif
 
        /*
-- 
2.45.2

Reply via email to