]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
ARM: imx: Enable MMU and dcache very early on i.MX8M
authorMarek Vasut <marex@denx.de>
Thu, 5 Sep 2024 15:35:00 +0000 (17:35 +0200)
committerFabio Estevam <festevam@gmail.com>
Wed, 11 Sep 2024 19:43:24 +0000 (16:43 -0300)
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 <marex@denx.de>
Reviewed-by: Peng Fan <peng.fan@nxp.com>
Reviewed-by: Fabio Estevam <festevam@gmail.com>
arch/arm/mach-imx/imx8m/soc.c

index f30178ae21373456a24b820f877b25683b8fecd9..986687e9ce40a6f138e0139f2d9ae0ff2ad943af 100644 (file)
@@ -32,6 +32,7 @@
 #include <imx_sip.h>
 #include <linux/bitops.h>
 #include <linux/bitfield.h>
+#include <linux/sizes.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -206,6 +207,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 +596,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
 
        /*