[U-Boot] [PATCH v2 3/3] sunxi: Normalise FEL support
Simon Glass
sjg at chromium.org
Mon Feb 9 23:23:17 CET 2015
Hi Siarhei,
On 7 February 2015 at 20:48, Siarhei Siamashka
<siarhei.siamashka at gmail.com> wrote:
> On Sat, 7 Feb 2015 10:47:30 -0700
> Simon Glass <sjg at chromium.org> wrote:
>
>> Make sunxi's FEL code fit with the normal U-Boot boot sequence instead of
>> creating its own. There are some #ifdefs required in start.S. Future work
>> will hopefully remove these.
>>
>> This series is available at u-boot-dm, branch sunxi-working.
>>
>> Signed-off-by: Simon Glass <sjg at chromium.org>
>> ---
>>
>> Changes in v2:
>> - Adjust for new save_boot_params() API
>> - Drop patch to change r0 to r2 in start.S
>> - Add #ifdefs to start.S to deal with FEL
>> - Use 'Fast Early Loader' as the full name for FEL
>
> Thanks for working on these patches. It looks like we are finally
> getting really close to resolving the sunxi FEL boot problem.
>
> Some comments are below.
>
>> arch/arm/cpu/armv7/start.S | 5 +-
>> arch/arm/cpu/armv7/sunxi/Makefile | 4 +-
>> arch/arm/cpu/armv7/sunxi/board.c | 21 ++++++++
>> arch/arm/cpu/armv7/sunxi/config.mk | 2 -
>> arch/arm/cpu/armv7/sunxi/fel_utils.S | 25 +++++++++
>> arch/arm/cpu/armv7/sunxi/u-boot-spl-fel.lds | 82 -----------------------------
>> arch/arm/include/asm/arch-sunxi/sys_proto.h | 10 ++++
>> board/sunxi/Kconfig | 10 ++++
>> include/configs/sunxi-common.h | 6 +--
>> scripts/Makefile.spl | 2 -
>> 10 files changed, 73 insertions(+), 94 deletions(-)
>> create mode 100644 arch/arm/cpu/armv7/sunxi/fel_utils.S
>> delete mode 100644 arch/arm/cpu/armv7/sunxi/u-boot-spl-fel.lds
>>
>> diff --git a/arch/arm/cpu/armv7/start.S b/arch/arm/cpu/armv7/start.S
>> index 9b49ece..098a83a 100644
>> --- a/arch/arm/cpu/armv7/start.S
>> +++ b/arch/arm/cpu/armv7/start.S
>> @@ -54,7 +54,8 @@ save_boot_params_ret:
>> * (OMAP4 spl TEXT_BASE is not 32 byte aligned.
>> * Continue to use ROM code vector only in OMAP4 spl)
>> */
>> -#if !(defined(CONFIG_OMAP44XX) && defined(CONFIG_SPL_BUILD))
>> +#if !(defined(CONFIG_OMAP44XX) && defined(CONFIG_SPL_BUILD)) && \
>> + !defined(CONFIG_SPL_FEL)
>
> Maybe we can just update the 'save_boot_params' function to save the
> important configuration registers and then undo this configuration
> in 'return_to_fel'? This allows us to avoid the sunxi specific ifdefs
> in the core ARM code.
>
> In this particular case, restoring VBAR and CPSR is important because
> the BROM code uses an IRQ handler for FEL (presumably USB related).
> And we want to ensure that this IRQ handler works properly again
> after resuming the FEL code.
We could indeed.
It would avoid the #ifdef but my understanding is that you might be
able to avoid having to 'return' to the BROM through another means. In
any case we could perhaps leave that change until the next release?
>
>> /* Set V=0 in CP15 SCTLR register - for VBAR to point to vector */
>> mrc p15, 0, r0, c1, c0, 0 @ Read CP15 SCTLR Register
>> bic r0, #CR_V @ V = 0
>> @@ -67,7 +68,9 @@ save_boot_params_ret:
>>
>> /* the mask ROM code should have PLL and others stable */
>> #ifndef CONFIG_SKIP_LOWLEVEL_INIT
>> +#ifndef CONFIG_SPL_FEL
>
> Same here.
>
>> bl cpu_init_cp15
>> +#endif
>> bl cpu_init_crit
>> #endif
>>
>> diff --git a/arch/arm/cpu/armv7/sunxi/Makefile b/arch/arm/cpu/armv7/sunxi/Makefile
>> index 48db744..c1b975a 100644
>> --- a/arch/arm/cpu/armv7/sunxi/Makefile
>> +++ b/arch/arm/cpu/armv7/sunxi/Makefile
>> @@ -38,7 +38,5 @@ obj-$(CONFIG_MACH_SUN5I) += dram_sun4i.o
>> obj-$(CONFIG_MACH_SUN6I) += dram_sun6i.o
>> obj-$(CONFIG_MACH_SUN7I) += dram_sun4i.o
>> obj-$(CONFIG_MACH_SUN8I) += dram_sun8i.o
>> -ifdef CONFIG_SPL_FEL
>> -obj-y += start.o
>> -endif
>> +obj-y += fel_utils.o
>> endif
>> diff --git a/arch/arm/cpu/armv7/sunxi/board.c b/arch/arm/cpu/armv7/sunxi/board.c
>> index 6e28bcd..b7492ac 100644
>> --- a/arch/arm/cpu/armv7/sunxi/board.c
>> +++ b/arch/arm/cpu/armv7/sunxi/board.c
>> @@ -27,6 +27,13 @@
>>
>> #include <linux/compiler.h>
>>
>> +struct fel_stash {
>> + uint32_t sp;
>> + uint32_t lr;
>> +};
>
> struct fel_stash {
> uint32_t sp;
> uint32_t lr;
> uint32_t cpsr;
> uint32_t sctlr;
> uint32_t vbar;
> uint32_t cr;
> };
>
>> +struct fel_stash fel_stash __attribute__((section(".data")));
>> +
>> static int gpio_init(void)
>> {
>> #if CONFIG_CONS_INDEX == 1 && defined(CONFIG_UART0_PORT_F)
>> @@ -65,6 +72,12 @@ static int gpio_init(void)
>> return 0;
>> }
>>
>> +void spl_board_load_image(void)
>> +{
>> + debug("Returning to FEL sp=%x, lr=%x\n", fel_stash.sp, fel_stash.lr);
>> + return_to_fel(fel_stash.sp, fel_stash.lr);
>> +}
>> +
>> void s_init(void)
>> {
>> #if defined CONFIG_MACH_SUN6I || defined CONFIG_MACH_SUN8I
>> @@ -95,6 +108,14 @@ void s_init(void)
>> */
>> u32 spl_boot_device(void)
>> {
>> + /*
>> + * Have we been asked to return to the FEL portion of the boot ROM?
>> + * TODO: We need a more robust test here, or bracket this with
>> + * #ifdef CONFIG_SPL_FEL.
>> + */
>> + if (fel_stash.lr >= 0xffff0000 && fel_stash.lr < 0xffff4000)
>> + return BOOT_DEVICE_BOARD;
>> return BOOT_DEVICE_MMC1;
>
> It is probably better to do it this way:
>
> #ifdef CONFIG_SPL_FEL
> return BOOT_DEVICE_BOARD;
> #else
> if (memcmp((void *)4, "eGON.BT0", 8) == 0)
> return BOOT_DEVICE_MMC1;
> else
> return BOOT_DEVICE_BOARD;
> #endif
>
> The memcmp (or equivalent code) ensures that it is compatible with
> https://github.com/ssvb/sunxi-tools/commit/aa7e1880986e5c9a825b08aed9dc5621b821805f
>
> Then the new 'fel spl u-boot-sunxi-with-spl.bin' command for loading
> and executing the SPL works fine without CONFIG_SPL_FEL defined
> (because the SD card specific "eGON.BT0" signature is replaced with
> the "eGON.FEL" signature by the 'fel' tool in the device memory
> before transferring control to the SPL code). Needless to say that
> the SPL built this way still works when written to the SD card.
>
> And if CONFIG_SPL_FEL is defined, then the FEL support still works in a
> legacy way (via 'fel write 0x2000 u-boot-spl.bin; fel exe 0x2000').
>
> We would only need to drop the legacy way in u-boot v2015.07 if the
> new one proves to be problem free by that time :-)
So you mean that we can drop CONFIG_SPL_FEL?
[snip]
>
> ENTRY(save_boot_params)
> ldr r0, =fel_stash
> str sp, [r0, #0]
> str lr, [r0, #4]
> mrs lr, cpsr @ Read CPSR
> str lr, [r0, #8]
> mrc p15, 0, lr, c1, c0, 0 @ Read CP15 SCTLR
> str lr, [r0, #12]
> mrc p15, 0, lr, c12, c0, 0 @ Read VBAR
> str lr, [r0, #16]
> mrc p15, 0, lr, c1, c0, 0 @ Read CP15 Control
> str lr, [r0, #20]
> b save_boot_params_ret
> ENDPROC(save_boot_params)
>
> ENTRY(return_to_fel)
> ldr r0, =fel_stash
> ldr lr, [r0, #20]
> mcr p15, 0, lr, c1, c0, 0 @ Write CP15 Control
> ldr lr, [r0, #16]
> mcr p15, 0, lr, c12, c0, 0 @ Write VBAR
> ldr lr, [r0, #12]
> mcr p15, 0, lr, c1, c0, 0 @ Write CP15 SCTLR
> ldr lr, [r0, #8]
> msr cpsr, lr @ Write CPSR
> ldr sp, [r0, #0]
> ldr lr, [r0, #4]
> bx lr
> ENDPROC(return_to_fel)
>
>
> This seems to work for me. However we probably might try to skip
> restoring some of these registers. Also somebody might want to
> review the order in which the registers should be restored.
I can certainly incorporate this into the patch.
Is that what you would prefer? It seems more complicated, and also a
bit odd to save a whole load of data that we then corrupt and restore,
but it is fine with me.
>
>> diff --git a/arch/arm/cpu/armv7/sunxi/u-boot-spl-fel.lds b/arch/arm/cpu/armv7/sunxi/u-boot-spl-fel.lds
>> deleted file mode 100644
>> index 928b7c1..0000000
>> --- a/arch/arm/cpu/armv7/sunxi/u-boot-spl-fel.lds
>> +++ /dev/null
>> @@ -1,82 +0,0 @@
>> -/*
>> - * (C) Copyright 2013
>> - * Henrik Nordstrom <henrik at henriknordstrom.net>
>> - *
>> - * SPDX-License-Identifier: GPL-2.0+
>> - */
>> -OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
>> -OUTPUT_ARCH(arm)
>> -ENTRY(s_init)
>> -SECTIONS
>> -{
>> - . = 0x00002000;
>> -
>> - . = ALIGN(4);
>> - .text :
>> - {
>> - *(.text.s_init)
>> - *(.text*)
>> - }
>> -
>> - . = ALIGN(4);
>> - .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
>> -
>> - . = ALIGN(4);
>> - .data : {
>> - *(.data*)
>> - }
>> -
>> - . = ALIGN(4);
>> - .u_boot_list : {
>> - KEEP(*(SORT(.u_boot_list*)));
>> - }
>> -
>> - . = ALIGN(4);
>> - . = .;
>> -
>> - . = ALIGN(4);
>> - .rel.dyn : {
>> - __rel_dyn_start = .;
>> - *(.rel*)
>> - __rel_dyn_end = .;
>> - }
>> -
>> - .dynsym : {
>> - __dynsym_start = .;
>> - *(.dynsym)
>> - }
>> -
>> - . = ALIGN(4);
>> - .note.gnu.build-id :
>> - {
>> - *(.note.gnu.build-id)
>> - }
>> - _end = .;
>> -
>> - . = ALIGN(4096);
>> - .mmutable : {
>> - *(.mmutable)
>> - }
>> -
>> - .bss_start __rel_dyn_start (OVERLAY) : {
>> - KEEP(*(.__bss_start));
>> - __bss_base = .;
>> - }
>> -
>> - .bss __bss_base (OVERLAY) : {
>> - *(.bss*)
>> - . = ALIGN(4);
>> - __bss_limit = .;
>> - }
>> -
>> - .bss_end __bss_limit (OVERLAY) : {
>> - KEEP(*(.__bss_end));
>> - }
>> -
>> - /DISCARD/ : { *(.dynstr*) }
>> - /DISCARD/ : { *(.dynamic*) }
>> - /DISCARD/ : { *(.plt*) }
>> - /DISCARD/ : { *(.interp*) }
>> - /DISCARD/ : { *(.gnu*) }
>> - /DISCARD/ : { *(.note*) }
>> -}
>> diff --git a/arch/arm/include/asm/arch-sunxi/sys_proto.h b/arch/arm/include/asm/arch-sunxi/sys_proto.h
>> index c3e636e..60a5bd8 100644
>> --- a/arch/arm/include/asm/arch-sunxi/sys_proto.h
>> +++ b/arch/arm/include/asm/arch-sunxi/sys_proto.h
>> @@ -13,4 +13,14 @@
>>
>> void sdelay(unsigned long);
>>
>> +/* return_to_fel() - Return to BROM from SPL
>> + *
>> + * This returns back into the BROM after U-Boot SPL has performed its initial
>> + * init. It uses the provided lr and sp to do so.
>> + *
>> + * @lr: BROM link register value (return address)
>> + * @sp: BROM stack pointer
>> + */
>> +void return_to_fel(uint32_t lr, uint32_t sp);
>> +
>> #endif
>> diff --git a/board/sunxi/Kconfig b/board/sunxi/Kconfig
>> index 4a21589..3eab81f 100644
>> --- a/board/sunxi/Kconfig
>> +++ b/board/sunxi/Kconfig
>> @@ -149,6 +149,16 @@ config SPL_FEL
>> bool "SPL/FEL mode support"
>> depends on SPL
>> default n
>> + help
>> + This enables support for Fast Early Loader (FEL) mode. This
>> + allows U-Boot to be loaded to the board over USB by the on-chip
>> + boot rom. U-Boot should be sent in two parts: SPL first, with
>> + 'fel write 0x2000 u-boot-spl.bin; fel exe 0x2000' then U-Boot with
>> + 'fel write 0x4a000000 u-boot.bin; fel exe 0x4a000000'. This option
>> + shrinks the amount of SRAM available to SPL, so only enable it if
>> + you need FEL. Note that enabling this option only allows FEL to be
>> + used; it is still possible to boot U-Boot from boot media. U-Boot
>> + SPL detects when it is being loaded using FEL.
>>
>> config UART0_PORT_F
>> bool "UART0 on MicroSD breakout board"
>> diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h
>> index 6cfd7e1..3becb4f 100644
>> --- a/include/configs/sunxi-common.h
>> +++ b/include/configs/sunxi-common.h
>> @@ -18,10 +18,8 @@
>> */
>> #define CONFIG_SUNXI /* sunxi family */
>> #ifdef CONFIG_SPL_BUILD
>> -#ifndef CONFIG_SPL_FEL
>> #define CONFIG_SYS_THUMB_BUILD /* Thumbs mode to save space in SPL */
>> #endif
>> -#endif
>>
>> #include <asm/arch/cpu.h> /* get chip and board defs */
>>
>> @@ -146,10 +144,10 @@
>> #define CONFIG_SPL_SERIAL_SUPPORT
>> #define CONFIG_SPL_LIBGENERIC_SUPPORT
>>
>> +#define CONFIG_SPL_BOARD_LOAD_IMAGE
>> +
>> #ifdef CONFIG_SPL_FEL
>>
>> -#define CONFIG_SPL_LDSCRIPT "arch/arm/cpu/armv7/sunxi/u-boot-spl-fel.lds"
>> -#define CONFIG_SPL_START_S_PATH "arch/arm/cpu/armv7/sunxi"
>> #define CONFIG_SPL_TEXT_BASE 0x2000
>> #define CONFIG_SPL_MAX_SIZE 0x4000 /* 16 KiB */
>>
>> diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl
>> index ecf3037..5a1962b 100644
>> --- a/scripts/Makefile.spl
>> +++ b/scripts/Makefile.spl
>> @@ -153,10 +153,8 @@ ALL-y += $(obj)/$(BOARD)-spl.bin
>> endif
>>
>> ifdef CONFIG_SUNXI
>> -ifndef CONFIG_SPL_FEL
>> ALL-y += $(obj)/sunxi-spl.bin
>> endif
>> -endif
>>
>> ifeq ($(CONFIG_SYS_SOC),"at91")
>> ALL-y += boot.bin
>
> One more theoretical concern is the placement of the stack in the legacy
> FEL mode after your changes. Now it seems to be moved to 0x8000, which
> might be fine though, according to the memory map from
>
> https://github.com/hno/Allwinner-Info/blob/master/FEL-usb/USB-protocol.txt
>
> If we want to preserve the old behaviour, then we would need to place
> it around 0x5d00.
I'm wondering if it might be better for you to take over and respin
this patch? My role has perhaps been to provide a proof-of-concept
implementation, but I don't need to do the final bit.
Let me know what you think.
Regards,
Simon
More information about the U-Boot
mailing list