diff mbox series

[v4,3/3] ARM: imx6: dh-imx6: Enable d-cache early in SPL

Message ID 20220817090611.3292993-4-pro@denx.de
State Superseded
Delegated to: Tom Rini
Headers show
Series ARM: imx6: dh-imx6: Enable d-cache early in SPL | expand

Commit Message

Philip Oberfichtner Aug. 17, 2022, 9:06 a.m. UTC
From: Marek Vasut <marex@denx.de>

Enable d-cache early in SPL right after DRAM is started up.
This reduces U-Boot proper load time by 650ms when loaded
from SPI NOR.

Signed-off-by: Marek Vasut <marex@denx.de>
Signed-off-by: Philip Oberfichtner <pro@denx.de>

---

Changes in v4:
        - Elaborate on dcache_disable() comment

Changes in v3:
        - Use newly introduced Kconfig symbol for dh_imx6_defconfig

Changes in v2:
        - Add comment to explain the relevance of dcache_disable()

 board/dhelectronics/dh_imx6/dh_imx6_spl.c | 32 +++++++++++++++++++++++
 configs/dh_imx6_defconfig                 |  1 +
 2 files changed, 33 insertions(+)

Comments

Marek Vasut Aug. 17, 2022, 9:24 a.m. UTC | #1
On 8/17/22 11:06, Philip Oberfichtner wrote:

[...]

> +void spl_board_prepare_for_boot(void)
> +{
> +	/*
> +	 * Flush dcache.

The dcache_disable() does not do any cache flushing, it just disables 
the Dcache enable C-bit.

> Without it U-Boot proper would hang at random locations. Presumably this is
> +	 * due to dirty cache lines remaining after SPL passes control. When U-Boot proper later on
> +	 * calls invalidate_dcache_all(), those dirty cache lines will get lost.
> +	 */

What about falcon boot mode starting Linux from SPL, could it fail the 
same way ?

> +	dcache_disable();
> +}

[...]
Philip Oberfichtner Aug. 17, 2022, 10:19 a.m. UTC | #2
Hi,

thanks for the feedback.

On Wed, 2022-08-17 at 11:24 +0200, Marek Vasut wrote:
> On 8/17/22 11:06, Philip Oberfichtner wrote:
> 
> [...]
> 
> > +void spl_board_prepare_for_boot(void)
> > +{
> > +       /*
> > +        * Flush dcache.
> 
> The dcache_disable() does not do any cache flushing, it just disables
> the Dcache enable C-bit.

See the following objdump jumping to flush_dcache_all(). The
implementation of dcache_disable() is in arch/arm/lib/cache-cp15.c.

$ ${CROSS_COMPILE}objdump spl/u-boot-spl --disassemble=dcache_disable
                                                                                             
spl/u-boot-spl:     file format elf32-littlearm                       
                                                                                             
                                                                                             
Disassembly of section .text:                                         
                                                                                             
0090b498 <dcache_disable>:                                            
  90b498:       b510            push    {r4, lr}                      
  90b49a:       ee11 3f10       mrc     15, 0, r3, cr1, cr0, {0}      
  90b49e:       075b            lsls    r3, r3, #29                   
  90b4a0:       d509            bpl.n   90b4b6 <dcache_disable+0x1e>  
  90b4a2:       ee11 4f10       mrc     15, 0, r4, cr1, cr0, {0}      
  90b4a6:       f7ff fbfb       bl      90aca0 <flush_dcache_all>     
  90b4aa:       f024 0405       bic.w   r4, r4, #5                    
  90b4ae:       ee01 4f10       mcr     15, 0, r4, cr1, cr0, {0}      
  90b4b2:       f3bf 8f6f       isb     sy                            
  90b4b6:       bd10            pop     {r4, pc}                      
$              

I'll add a note to the comment about flush_dcache_all() being called. 


> 
> > Without it U-Boot proper would hang at random locations. Presumably
> > this is
> > +        * due to dirty cache lines remaining after SPL passes
> > control. When U-Boot proper later on
> > +        * calls invalidate_dcache_all(), those dirty cache lines
> > will get lost.
> > +        */
> 
> What about falcon boot mode starting Linux from SPL, could it fail
> the 
> same way ?

Yes, assuming my dirty-cache-line hypothesis is correct. I'll
generalize the comment in V5.

> 
> > +       dcache_disable();
> > +}
> 
> [...]
Marek Vasut Aug. 17, 2022, 10:51 a.m. UTC | #3
On 8/17/22 12:19, Philip Oberfichtner wrote:
> Hi,
> 
> thanks for the feedback.
> 
> On Wed, 2022-08-17 at 11:24 +0200, Marek Vasut wrote:
>> On 8/17/22 11:06, Philip Oberfichtner wrote:
>>
>> [...]
>>
>>> +void spl_board_prepare_for_boot(void)
>>> +{
>>> +       /*
>>> +        * Flush dcache.
>>
>> The dcache_disable() does not do any cache flushing, it just disables
>> the Dcache enable C-bit.
> 
> See the following objdump jumping to flush_dcache_all(). The
> implementation of dcache_disable() is in arch/arm/lib/cache-cp15.c.
> 
> $ ${CROSS_COMPILE}objdump spl/u-boot-spl --disassemble=dcache_disable
>                                                                                               
> spl/u-boot-spl:     file format elf32-littlearm
>                                                                                               
>                                                                                               
> Disassembly of section .text:
>                                                                                               
> 0090b498 <dcache_disable>:
>    90b498:       b510            push    {r4, lr}
>    90b49a:       ee11 3f10       mrc     15, 0, r3, cr1, cr0, {0}
>    90b49e:       075b            lsls    r3, r3, #29
>    90b4a0:       d509            bpl.n   90b4b6 <dcache_disable+0x1e>
>    90b4a2:       ee11 4f10       mrc     15, 0, r4, cr1, cr0, {0}
>    90b4a6:       f7ff fbfb       bl      90aca0 <flush_dcache_all>
>    90b4aa:       f024 0405       bic.w   r4, r4, #5
>    90b4ae:       ee01 4f10       mcr     15, 0, r4, cr1, cr0, {0}
>    90b4b2:       f3bf 8f6f       isb     sy
>    90b4b6:       bd10            pop     {r4, pc}
> $
> 
> I'll add a note to the comment about flush_dcache_all() being called.

Doh, now I see it in there too, among the wall of ifdeffery in 
cache_disable() . Thanks

[...]
diff mbox series

Patch

diff --git a/board/dhelectronics/dh_imx6/dh_imx6_spl.c b/board/dhelectronics/dh_imx6/dh_imx6_spl.c
index e49e97724a..580b98811c 100644
--- a/board/dhelectronics/dh_imx6/dh_imx6_spl.c
+++ b/board/dhelectronics/dh_imx6/dh_imx6_spl.c
@@ -6,6 +6,7 @@ 
  */
 
 #include <common.h>
+#include <cpu_func.h>
 #include <init.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/crm_regs.h>
@@ -14,11 +15,13 @@ 
 #include <asm/arch/mx6-ddr.h>
 #include <asm/arch/mx6-pins.h>
 #include <asm/arch/sys_proto.h>
+#include <asm/cache.h>
 #include <asm/gpio.h>
 #include <asm/mach-imx/boot_mode.h>
 #include <asm/mach-imx/iomux-v3.h>
 #include <asm/mach-imx/mxc_i2c.h>
 #include <asm/io.h>
+#include <asm/system.h>
 #include <errno.h>
 #include <fuse.h>
 #include <fsl_esdhc_imx.h>
@@ -610,6 +613,20 @@  static void dhcom_spl_dram_init(void)
 	}
 }
 
+void dram_bank_mmu_setup(int bank)
+{
+	int i;
+
+	set_section_dcache(ROMCP_ARB_BASE_ADDR >> MMU_SECTION_SHIFT, DCACHE_DEFAULT_OPTION);
+	set_section_dcache(IRAM_BASE_ADDR >> MMU_SECTION_SHIFT, DCACHE_DEFAULT_OPTION);
+
+	for (i = MMDC0_ARB_BASE_ADDR >> MMU_SECTION_SHIFT;
+			i < ((MMDC0_ARB_BASE_ADDR >> MMU_SECTION_SHIFT) +
+			(SZ_1G >> MMU_SECTION_SHIFT));
+			i++)
+		set_section_dcache(i, DCACHE_DEFAULT_OPTION);
+}
+
 void board_init_f(ulong dummy)
 {
 	/* setup AIPS and disable watchdog */
@@ -636,9 +653,24 @@  void board_init_f(ulong dummy)
 	/* DDR3 initialization */
 	dhcom_spl_dram_init();
 
+	/* Set up early MMU tables at the beginning of DRAM and start d-cache */
+	gd->arch.tlb_addr = MMDC0_ARB_BASE_ADDR + SZ_32M;
+	gd->arch.tlb_size = PGTABLE_SIZE;
+	enable_caches();
+
 	/* Clear the BSS. */
 	memset(__bss_start, 0, __bss_end - __bss_start);
 
 	/* load/boot image from boot device */
 	board_init_r(NULL, 0);
 }
+
+void spl_board_prepare_for_boot(void)
+{
+	/*
+	 * Flush dcache. Without it U-Boot proper would hang at random locations. Presumably this is
+	 * due to dirty cache lines remaining after SPL passes control. When U-Boot proper later on
+	 * calls invalidate_dcache_all(), those dirty cache lines will get lost.
+	 */
+	dcache_disable();
+}
diff --git a/configs/dh_imx6_defconfig b/configs/dh_imx6_defconfig
index 051816f719..1be6ae62ce 100644
--- a/configs/dh_imx6_defconfig
+++ b/configs/dh_imx6_defconfig
@@ -1,4 +1,5 @@ 
 CONFIG_ARM=y
+CONFIG_SPL_SYS_L2_PL310=y
 CONFIG_ARCH_MX6=y
 CONFIG_SYS_TEXT_BASE=0x17800000
 CONFIG_SYS_MALLOC_F_LEN=0x1000