[PATCH] ARM: i.MX27: Fix NAND boot with newer gcc

Baeuerle, Florian Florian.Baeuerle at allegion.com
Tue Sep 18 08:40:36 PDT 2018


Tested-by: Florian Bäuerle <florian.baeuerle at allegion.com>

Thanks!

Am Dienstag, den 18.09.2018, 16:53 +0200 schrieb Sascha Hauer:
> This is a fix for a very weird icache problem when booting from NAND.
> With a OSELAS-2018.01 toolchain imx27_barebox_boot_nand_external() is
> compiled like this:
> 
> 0000063c <imx27_barebox_boot_nand_external>:
>      63c:	e92d4010 	push	{r4, lr}
>      640:	e1a0200f 	mov	r2, pc
>      644:	e282230a 	add	r2, r2, #671088640	; 0x28000000
>      648:	e3520b02 	cmp	r2, #2048	; 0x800
>      64c:	9a000012 	bls	69c <imx27_barebox_boot_nand_external+0x60>
>      650:	eb000034 	bl	728 <imx27_barebox_entry>
>      654:	e592c000 	ldr	ip, [r2]
>      658:	e2822004 	add	r2, r2, #4
>      65c:	e580c000 	str	ip, [r0]
>      660:	e1520001 	cmp	r2, r1
>      664:	e2820332 	add	r0, r2, #-939524096	; 0xc8000000
>      668:	1afffff9 	bne	654 <imx27_barebox_boot_nand_external+0x18>
>      66c:	e1a00003 	mov	r0, r3
>      670:	e59f2034 	ldr	r2, [pc, #52]	; 6ac
> <imx27_barebox_boot_nand_external+0x70>
>      674:	e2401376 	sub	r1, r0, #-671088639	; 0xd8000001
>      678:	e59f3030 	ldr	r3, [pc, #48]	; 6b0
> <imx27_barebox_boot_nand_external+0x74>
>      67c:	e1510002 	cmp	r1, r2
>      680:	93c004ff 	bicls	r0, r0, #-16777216	; 0xff000000
>      684:	e1a03a83 	lsl	r3, r3, #21
>      688:	e1a03aa3 	lsr	r3, r3, #21
>      68c:	93c0073e 	bicls	r0, r0, #16252928	; 0xf80000
>      690:	e283320a 	add	r3, r3, #-1610612736	; 0xa0000000
>      694:	9280020a 	addls	r0, r0, #-1610612736	; 0xa0000000
>      698:	e12fff33 	blx	r3
>      69c:	e1a03000 	mov	r3, r0
>      6a0:	e3a02336 	mov	r2, #-671088640	; 0xd8000000
>      6a4:	e59f1008 	ldr	r1, [pc, #8]	; 6b4
> <imx27_barebox_boot_nand_external+0x78>
>      6a8:	eaffffec 	b	660 <imx27_barebox_boot_nand_external+0x24>
>      6ac:	0007fffe 	.word	0x0007fffe
>      6b0:	00000604 	.word	0x00000604
>      6b4:	d8000800 	.word	0xd8000800
> 
> From 0x64c the code jumps to 0x69c and then back to 0x660. The jump to
> 0x69c triggers a icache line fetch which works fine, but then when the
> function continues and the code enters the same instruction cache line
> at 0x680 again then only garbage is executed, most of the time we end up
> in an endless loop and the CPU jumps back somewhere at the beginning of
> the function.
> 
> I have carefully added nops right before the out of line code block.
> When there are enough nops to move the block to the next cache line
> then the code works again.
> 
> That of course is no solution to the problem. Since I am out of ideas
> what the real issue is let's just disable the icache in this function
> and re-enable it in the next function. This seems to solve the problem.
> 
> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> ---
>  arch/arm/mach-imx/external-nand-boot.c | 9 ++++++++-
>  1 file changed, 8 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm/mach-imx/external-nand-boot.c b/arch/arm/mach-
> imx/external-nand-boot.c
> index 17878e400b..745a129b23 100644
> --- a/arch/arm/mach-imx/external-nand-boot.c
> +++ b/arch/arm/mach-imx/external-nand-boot.c
> @@ -323,10 +323,14 @@ void __noreturn
> BARE_INIT_FUNCTION(imx##soc##_boot_nand_external_cont)  \
>  {									\
>  	unsigned long nfc_base = MX##soc##_NFC_BASE_ADDR;		\
>  	void *sdram = (void *)MX##soc##_CSD0_BASE_ADDR;			\
> -	uint32_t image_size;						\
> +	uint32_t image_size, r;						\
>  									\
>  	image_size = *(uint32_t *)(sdram + 0x2c);			\
>  									\
> +	r = get_cr();							\
> +	r |= CR_I;							\
> +	set_cr(r);							\
> +									\
>  	imx##soc##_nand_load_image(sdram,				\
>  			image_size,					\
>  			(void *)nfc_base,				\
> @@ -347,6 +351,9 @@ void __noreturn
> BARE_INIT_FUNCTION(imx##soc##_barebox_boot_nand_external) \
>  	int i;								\
>  	void __noreturn (*fn)(void *);					\
>  									\
> +	r = get_cr();							\
> +	r &= ~CR_I;							\
> +	set_cr(r);							\
>  	/* skip NAND boot if not running from NFC space */		\
>  	r = get_pc();							\
>  	if (r < nfc_base || r > nfc_base + 0x800)			\


More information about the barebox mailing list