From ef70a42f0ffc6b43f719810c4e3861c55c2eefbc Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Tue, 10 Oct 2017 16:21:01 +0200 Subject: arm: boot0 hook: move boot0 hook before '_start' The boot0 hook on ARM does not insert its payload before the vector table. This is both a mismatch with thec comment above it and contradict usage of the boot0 hook on ARM64. To fix this (and unify the semantics for ARM and ARM64), we change the boot0-hook semantics on ARM to match those on ARM64: (1) if a boot0-hook is present it is inserted at the start of the image (2) if a boot0-hook is present, emitting the ARM vector table (and the _start) symbol are suppressed in vectors.S and the boot0-hook has full control over where and when it wants to emit these Signed-off-by: Philipp Tomsich --- arch/arm/include/asm/arch-rockchip/boot0.h | 1 - arch/arm/lib/vectors.S | 54 +++++++++++++++++++----------- 2 files changed, 35 insertions(+), 20 deletions(-) (limited to 'arch') diff --git a/arch/arm/include/asm/arch-rockchip/boot0.h b/arch/arm/include/asm/arch-rockchip/boot0.h index 72d264bcbe9..455d8428d80 100644 --- a/arch/arm/include/asm/arch-rockchip/boot0.h +++ b/arch/arm/include/asm/arch-rockchip/boot0.h @@ -1,4 +1,3 @@ - /* * Copyright 2017 Theobroma Systems Design und Consulting GmbH * diff --git a/arch/arm/lib/vectors.S b/arch/arm/lib/vectors.S index 101909103e4..9cb0d2ef361 100644 --- a/arch/arm/lib/vectors.S +++ b/arch/arm/lib/vectors.S @@ -15,6 +15,22 @@ #include +/* + * A macro to allow insertion of an ARM exception vector either + * for the non-boot0 case or by a boot0-header. + */ + .macro ARM_VECTORS + b reset + ldr pc, _undefined_instruction + ldr pc, _software_interrupt + ldr pc, _prefetch_abort + ldr pc, _data_abort + ldr pc, _not_used + ldr pc, _irq + ldr pc, _fiq + .endm + + /* ************************************************************************* * @@ -35,6 +51,23 @@ .section ".vectors", "ax" +#if defined(CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK) +/* + * Various SoCs need something special and SoC-specific up front in + * order to boot, allow them to set that in their boot0.h file and then + * use it here. + * + * To allow a boot0 hook to insert a 'special' sequence after the vector + * table (e.g. for the socfpga), the presence of a boot0 hook supresses + * the below vector table and assumes that the vector table is filled in + * by the boot0 hook. The requirements for a boot0 hook thus are: + * (1) defines '_start:' as appropriate + * (2) inserts the vector table using ARM_VECTORS as appropriate + */ +#include + +#else + /* ************************************************************************* * @@ -46,28 +79,11 @@ */ _start: - #ifdef CONFIG_SYS_DV_NOR_BOOT_CFG .word CONFIG_SYS_DV_NOR_BOOT_CFG #endif - - b reset - ldr pc, _undefined_instruction - ldr pc, _software_interrupt - ldr pc, _prefetch_abort - ldr pc, _data_abort - ldr pc, _not_used - ldr pc, _irq - ldr pc, _fiq - -#ifdef CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK -/* - * Various SoCs need something special and SoC-specific up front in - * order to boot, allow them to set that in their boot0.h file and then - * use it here. - */ -#include -#endif + ARM_VECTORS +#endif /* !defined(CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK) */ /* ************************************************************************* -- cgit v1.3.1 From cee7470cd8a386802e38c6bde8ce62fbc8218a86 Mon Sep 17 00:00:00 2001 From: Kever Yang Date: Tue, 10 Oct 2017 16:21:02 +0200 Subject: rockchip: boot0: align to 0x20 for armv7 '_start' The '_start' is using as vector table base address, and will write to VBAR register, so it needs to be aligned to 0x20 for armv7. Signed-off-by: Kever Yang [Updated to current code base:] Signed-off-by: Philipp Tomsich --- arch/arm/include/asm/arch-rockchip/boot0.h | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/include/asm/arch-rockchip/boot0.h b/arch/arm/include/asm/arch-rockchip/boot0.h index 455d8428d80..f7c614669cf 100644 --- a/arch/arm/include/asm/arch-rockchip/boot0.h +++ b/arch/arm/include/asm/arch-rockchip/boot0.h @@ -6,12 +6,13 @@ /* * Execution starts on the instruction following this 4-byte header - * (containing the magic 'RK33'). + * (containing the magic 'RK30', 'RK31', 'RK32' or 'RK33'). This + * magic constant will be written into the final image by the rkimage + * tool, but we need to reserve space for it here. * * To make life easier for everyone, we build the SPL binary with * space for this 4-byte header already included in the binary. */ - #ifdef CONFIG_SPL_BUILD /* * We need to add 4 bytes of space for the 'RK33' at the @@ -26,6 +27,15 @@ b reset /* may be overwritten --- should be 'nop' or a 'b reset' */ #endif b reset +#if !defined(CONFIG_ARM64) + /* + * For armv7, the addr '_start' will used as vector start address + * and write to VBAR register, which needs to aligned to 0x20. + */ + .align(5) +_start: + ARM_VECTORS +#endif #if defined(CONFIG_ROCKCHIP_RK3399) && defined(CONFIG_SPL_BUILD) .space CONFIG_ROCKCHIP_SPL_RESERVE_IRAM /* space for the ATF data */ -- cgit v1.3.1 From 14ad6eb264f80975ace3d2cd5420d1a9f8a15468 Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Tue, 10 Oct 2017 16:21:03 +0200 Subject: rockchip: enable boot0-hook for all Rockchip SoCs Rockchip SoCs bootrom design is like this: - First 2KB or 4KB internal memory is for bootrom stack and heap; - Then the first 4-byte suppose to be a TAG like 'RK33'; - The the following memory address end with '0004' is the first instruction load and running by bootrom; Let's use the boot0 hook to reserve the first 4-byte tag for all the Rockchip SoCs. Signed-off-by: Philipp Tomsich [Commit message taken from an older patch by:] Signed-off-by: Kever Yang --- arch/arm/Kconfig | 1 + arch/arm/mach-rockchip/Kconfig | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 94ad8056844..ca386decfe8 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1130,6 +1130,7 @@ config ARCH_ROCKCHIP select DM_USB if USB select DM_PWM select DM_REGULATOR + select ENABLE_ARM_SOC_BOOT0_HOOK imply CMD_FASTBOOT imply FASTBOOT imply FAT_WRITE diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig index d9b25d5de4e..31e9864c8da 100644 --- a/arch/arm/mach-rockchip/Kconfig +++ b/arch/arm/mach-rockchip/Kconfig @@ -74,7 +74,6 @@ config ROCKCHIP_RK3368 imply SPL_SEPARATE_BSS imply SPL_SERIAL_SUPPORT imply TPL_SERIAL_SUPPORT - select ENABLE_ARM_SOC_BOOT0_HOOK select DEBUG_UART_BOARD_INIT select SYS_NS16550 help @@ -112,7 +111,6 @@ config ROCKCHIP_RK3399 select SPL_SEPARATE_BSS select SPL_SERIAL_SUPPORT select SPL_DRIVERS_MISC_SUPPORT - select ENABLE_ARM_SOC_BOOT0_HOOK select DEBUG_UART_BOARD_INIT help The Rockchip RK3399 is a ARM-based SoC with a dual-core Cortex-A72 -- cgit v1.3.1 From a002077d7d7535a974c3fe7e9ab85e5e80f0bf59 Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Tue, 10 Oct 2017 16:21:07 +0200 Subject: socfpga: boot0 hook: adjust to unified boot0 semantics With the updated boot0 semantics (i.e. giving the boot0-hook control over when and where the vector table is emitted), the boot0-hook for the socfpga needs to be adjusted. Signed-off-by: Philipp Tomsich --- arch/arm/mach-socfpga/include/mach/boot0.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-socfpga/include/mach/boot0.h b/arch/arm/mach-socfpga/include/mach/boot0.h index 22d9e7f7afb..d6b9435d333 100644 --- a/arch/arm/mach-socfpga/include/mach/boot0.h +++ b/arch/arm/mach-socfpga/include/mach/boot0.h @@ -7,6 +7,9 @@ #ifndef __BOOT0_H #define __BOOT0_H +_start: + ARM_VECTORS + #ifdef CONFIG_SPL_BUILD .balignl 64,0xf33db33f; -- cgit v1.3.1 From 62269f02ab8d8f85cc96b7bc2b10f74d67d0bb6b Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Tue, 10 Oct 2017 16:21:08 +0200 Subject: bcm235xx: boot0 hook: adjust to unified boot0 semantics This updates the BCM235xx boot0-hook to the updated boot0 semantics by emitting _start and the vector table before the boot0 hook (as was the case before). Signed-off-by: Philipp Tomsich Version-changes: 5 - ran 'whitespace-cleanup' --- arch/arm/include/asm/arch-bcm235xx/boot0.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/arm/include/asm/arch-bcm235xx/boot0.h b/arch/arm/include/asm/arch-bcm235xx/boot0.h index a747bd38233..28f05ba32d0 100644 --- a/arch/arm/include/asm/arch-bcm235xx/boot0.h +++ b/arch/arm/include/asm/arch-bcm235xx/boot0.h @@ -5,5 +5,7 @@ */ /* BOOT0 header information */ +_start: + ARM_VECTORS .word 0xbabeface .word _end - _start -- cgit v1.3.1 From 16d761e3dd8911760bb87d7c983cdea79d8540e3 Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Tue, 10 Oct 2017 16:21:09 +0200 Subject: bcm281xx: boot0 hook: adjust to unified boot0 semantics This updates the BCM281xx boot0-hook to the updated boot0 semantics by emitting _start and the vector table before the boot0 hook (as was the case before). Signed-off-by: Philipp Tomsich --- arch/arm/include/asm/arch-bcm281xx/boot0.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/arm/include/asm/arch-bcm281xx/boot0.h b/arch/arm/include/asm/arch-bcm281xx/boot0.h index a747bd38233..28f05ba32d0 100644 --- a/arch/arm/include/asm/arch-bcm281xx/boot0.h +++ b/arch/arm/include/asm/arch-bcm281xx/boot0.h @@ -5,5 +5,7 @@ */ /* BOOT0 header information */ +_start: + ARM_VECTORS .word 0xbabeface .word _end - _start -- cgit v1.3.1 From b377d22264178122e72c18c4d5d5ab2d4585cfdb Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Tue, 10 Oct 2017 16:21:10 +0200 Subject: rockchip: boot0 hook: support early return for RK3188/RK3066-style BROM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some Rockchip BROM versions (e.g. the RK3188 and RK3066) first read 1KB data from NAND into SRAM and executes it. Then, following a return to bootrom, the BROM loads additional code to SRAM (not overwriting the first block read) and reenters at the same address as the first time. To support booting either a TPL (on the RK3066) or SPL (on the RK3188) using this model of having to count entries, this commit adds code to the boot0 hook to track the number of entries and handle them accordingly. Signed-off-by: Philipp Tomsich Signed-off-by: Paweł Jarosz Tested-by: Andy Yan --- arch/arm/include/asm/arch-rockchip/boot0.h | 25 +++++++++++++++++++------ arch/arm/mach-rockchip/Kconfig | 28 ++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/arm/include/asm/arch-rockchip/boot0.h b/arch/arm/include/asm/arch-rockchip/boot0.h index f7c614669cf..af3a733e984 100644 --- a/arch/arm/include/asm/arch-rockchip/boot0.h +++ b/arch/arm/include/asm/arch-rockchip/boot0.h @@ -19,12 +19,25 @@ * beginning of the executable. However, as we want to keep * this generic and make it applicable to builds that are like * the RK3368 (TPL needs this, SPL doesn't) or the RK3399 (no - * TPL, but extra space needed in the SPL), we simply repeat - * the 'b reset' with the expectation that the first one will - * be overwritten, if this is the first stage contained in the - * final image created with mkimage)... + * TPL, but extra space needed in the SPL), we simply insert + * a branch-to-next-instruction-word with the expectation that + * the first one may be overwritten, if this is the first stage + * contained in the final image created with mkimage)... */ - b reset /* may be overwritten --- should be 'nop' or a 'b reset' */ + b 1f /* if overwritten, entry-address is at the next word */ +1: +#endif +#if CONFIG_IS_ENABLED(ROCKCHIP_EARLYRETURN_TO_BROM) + adr r3, entry_counter + ldr r0, [r3] + cmp r0, #1 /* check if entry_counter == 1 */ + beq reset /* regular bootup */ + add r0, #1 + str r0, [r3] /* increment the entry_counter in memory */ + mov r0, #0 /* return 0 to the BROM to signal 'OK' */ + bx lr /* return control to the BROM */ +entry_counter: + .word 0 #endif b reset #if !defined(CONFIG_ARM64) @@ -32,7 +45,7 @@ * For armv7, the addr '_start' will used as vector start address * and write to VBAR register, which needs to aligned to 0x20. */ - .align(5) + .align(5), 0x0 _start: ARM_VECTORS #endif diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig index 31e9864c8da..d59a1d5ccb2 100644 --- a/arch/arm/mach-rockchip/Kconfig +++ b/arch/arm/mach-rockchip/Kconfig @@ -158,6 +158,34 @@ config ROCKCHIP_SPL_RESERVE_IRAM config ROCKCHIP_BROM_HELPER bool +config SPL_ROCKCHIP_EARLYRETURN_TO_BROM + bool "SPL requires early-return (for RK3188-style BROM) to BROM" + depends on SPL && ENABLE_ARM_SOC_BOOT0_HOOK + help + Some Rockchip BROM variants (e.g. on the RK3188) load the + first stage in segments and enter multiple times. E.g. on + the RK3188, the first 1KB of the first stage are loaded + first and entered; after returning to the BROM, the + remainder of the first stage is loaded, but the BROM + re-enters at the same address/to the same code as previously. + + This enables support code in the BOOT0 hook for the SPL stage + to allow multiple entries. + +config TPL_ROCKCHIP_EARLYRETURN_TO_BROM + bool "TPL requires early-return (for RK3188-style BROM) to BROM" + depends on TPL && ENABLE_ARM_SOC_BOOT0_HOOK + help + Some Rockchip BROM variants (e.g. on the RK3188) load the + first stage in segments and enter multiple times. E.g. on + the RK3188, the first 1KB of the first stage are loaded + first and entered; after returning to the BROM, the + remainder of the first stage is loaded, but the BROM + re-enters at the same address/to the same code as previously. + + This enables support code in the BOOT0 hook for the TPL stage + to allow multiple entries. + config SPL_MMC_SUPPORT default y if !SPL_ROCKCHIP_BACK_TO_BROM -- cgit v1.3.1 From 7776cc011df4565ed6cf0be65d33ccf28c2fffab Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Tue, 10 Oct 2017 16:21:11 +0200 Subject: arm: make save_boot_params_ret prototype visible for AArch64 The save_boot_params_ret() prototype (for those of us, that have a valid SP on entry and can implement save_boot_params() in C), was previously only defined for !defined(CONFIG_ARM64). This moves the declaration to a common block to ensure the prototype is available to everyone that might need it. Signed-off-by: Philipp Tomsich Tested-by: Andy Yan --- arch/arm/include/asm/system.h | 62 +++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 31 deletions(-) (limited to 'arch') diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 1d7d4f35c4f..4f043cad0ba 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h @@ -332,37 +332,6 @@ void psci_arch_init(void); #ifndef __ASSEMBLY__ -/** - * save_boot_params() - Save boot parameters before starting reset sequence - * - * If you provide this function it will be called immediately U-Boot starts, - * both for SPL and U-Boot proper. - * - * All registers are unchanged from U-Boot entry. No registers need be - * preserved. - * - * This is not a normal C function. There is no stack. Return by branching to - * save_boot_params_ret. - * - * void save_boot_params(u32 r0, u32 r1, u32 r2, u32 r3); - */ - -/** - * save_boot_params_ret() - Return from save_boot_params() - * - * If you provide save_boot_params(), then you should jump back to this - * function when done. Try to preserve all registers. - * - * If your implementation of save_boot_params() is in C then it is acceptable - * to simply call save_boot_params_ret() at the end of your function. Since - * there is no link register set up, you cannot just exit the function. U-Boot - * will return to the (initialised) value of lr, and likely crash/hang. - * - * If your implementation of save_boot_params() is in assembler then you - * should use 'b' or 'bx' to return to save_boot_params_ret. - */ -void save_boot_params_ret(void); - #ifdef CONFIG_ARMV7_LPAE void switch_to_hypervisor_ret(void); #endif @@ -555,6 +524,37 @@ void mmu_page_table_flush(unsigned long start, unsigned long stop); #endif /* CONFIG_ARM64 */ #ifndef __ASSEMBLY__ +/** + * save_boot_params() - Save boot parameters before starting reset sequence + * + * If you provide this function it will be called immediately U-Boot starts, + * both for SPL and U-Boot proper. + * + * All registers are unchanged from U-Boot entry. No registers need be + * preserved. + * + * This is not a normal C function. There is no stack. Return by branching to + * save_boot_params_ret. + * + * void save_boot_params(u32 r0, u32 r1, u32 r2, u32 r3); + */ + +/** + * save_boot_params_ret() - Return from save_boot_params() + * + * If you provide save_boot_params(), then you should jump back to this + * function when done. Try to preserve all registers. + * + * If your implementation of save_boot_params() is in C then it is acceptable + * to simply call save_boot_params_ret() at the end of your function. Since + * there is no link register set up, you cannot just exit the function. U-Boot + * will return to the (initialised) value of lr, and likely crash/hang. + * + * If your implementation of save_boot_params() is in assembler then you + * should use 'b' or 'bx' to return to save_boot_params_ret. + */ +void save_boot_params_ret(void); + /** * Change the cache settings for a region. * -- cgit v1.3.1 From ff143d55564373c2a5e8a128a71223f26ee2420f Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Tue, 10 Oct 2017 16:21:12 +0200 Subject: arm: mark save_boot_params_ret as a function As no '.type' was set for save_boot_params_ret in start.S, binutils did not track whether it was emitted as A32 or T32. By properly marking save_boot_params_ret as a potential function entry, we can make sure that the compiler will insert the appropriate instructions for branching to save_boot_params_ret both for call-sites emitted as A32 and T32. Reported-by: Andy Yan Signed-off-by: Philipp Tomsich Tested-by: Andy Yan --- arch/arm/cpu/armv7/start.S | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/arm/cpu/armv7/start.S b/arch/arm/cpu/armv7/start.S index 7b84a7a0f16..95a0b5224b9 100644 --- a/arch/arm/cpu/armv7/start.S +++ b/arch/arm/cpu/armv7/start.S @@ -31,6 +31,7 @@ .globl reset .globl save_boot_params_ret + .type save_boot_params_ret,%function #ifdef CONFIG_ARMV7_LPAE .global switch_to_hypervisor_ret #endif -- cgit v1.3.1 From b4806d6f1f82f0a2d76b7206bdc5e4ba7d567b6f Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Tue, 10 Oct 2017 16:21:13 +0200 Subject: arm: provide a PCS-compliant setjmp implementation The previous setjmp-implementation (as a static inline function that contained an 'asm volatile' sequence) was extremely fragile: (some versions of) GCC optimised the set of registers. One critical example was the removal of 'r9' from the clobber list, if -ffixed-reg9 was supplied. To increase robustness and ensure PCS-compliant behaviour, the setjmp and longjmp implementation are now in assembly and closely match what one would expect to find in a libc implementation. Signed-off-by: Philipp Tomsich Tested-by: Andy Yan --- arch/arm/include/asm/setjmp.h | 94 ++++++------------------------------------- arch/arm/lib/Makefile | 6 +++ arch/arm/lib/setjmp.S | 37 +++++++++++++++++ arch/arm/lib/setjmp_aarch64.S | 42 +++++++++++++++++++ 4 files changed, 98 insertions(+), 81 deletions(-) create mode 100644 arch/arm/lib/setjmp.S create mode 100644 arch/arm/lib/setjmp_aarch64.S (limited to 'arch') diff --git a/arch/arm/include/asm/setjmp.h b/arch/arm/include/asm/setjmp.h index c3399a7e15a..517beebdeab 100644 --- a/arch/arm/include/asm/setjmp.h +++ b/arch/arm/include/asm/setjmp.h @@ -1,6 +1,6 @@ /* - * (C) Copyright 2016 - * Alexander Graf + * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH + * (C) Copyright 2016 Alexander Graf * * SPDX-License-Identifier: GPL-2.0+ */ @@ -8,89 +8,21 @@ #ifndef _SETJMP_H_ #define _SETJMP_H_ 1 +/* + * This really should be opaque, but the EFI implementation wrongly + * assumes that a 'struct jmp_buf_data' is defined. + */ struct jmp_buf_data { - ulong target; - ulong regs[5]; - int ret; -}; - -typedef struct jmp_buf_data jmp_buf[1]; - -static inline int setjmp(jmp_buf jmp) -{ - jmp->ret = 0; - -#ifdef CONFIG_ARM64 - asm volatile( - "adr x1, jmp_target\n" - "str x1, %0\n" - "stp x26, x27, %1\n" - "stp x28, x29, %2\n" - "mov x1, sp\n" - "str x1, %3\n" - "jmp_target: " - : "=m" (jmp->target), "=m" (jmp->regs[0]), - "=m" (jmp->regs[2]), "=m" (jmp->regs[4]) - : - : "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", - "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", - "x16", "x17", "x18", "x19", "x20", "x21", "x22", - "x23", "x24", "x25", /* x26, x27, x28, x29, sp */ - "x30", "cc", "memory"); -#else - asm volatile( -#if CONFIG_IS_ENABLED(SYS_THUMB_BUILD) - ".align 2\n" - "adr r0, jmp_target\n" - "add r0, r0, $1\n" +#if defined(__aarch64__) + u64 regs[13]; #else - "adr r0, jmp_target\n" -#endif - "mov r1, %0\n" - "mov r2, sp\n" - "stm r1!, {r0, r2, r4, r5, r6, r7}\n" - ".align 2\n" - "jmp_target: \n" - : - : "l" (&jmp->target) - : "r0", "r1", "r2", "r3", /* "r4", "r5", "r6", "r7", */ - "r8", "r9", "r10", "r11", /* sp, */ "ip", "lr", - "cc", "memory"); -#endif - - return jmp->ret; -} - -static inline __noreturn void longjmp(jmp_buf jmp, int ret) -{ - jmp->ret = ret; - -#ifdef CONFIG_ARM64 - asm volatile( - "ldr x0, %0\n" - "ldr x1, %3\n" - "mov sp, x1\n" - "ldp x26, x27, %1\n" - "ldp x28, x25, %2\n" - "mov x29, x25\n" - "br x0\n" - : - : "m" (jmp->target), "m" (jmp->regs[0]), "m" (jmp->regs[2]), - "m" (jmp->regs[4]) - : "x0", "x1", "x25", "x26", "x27", "x28"); -#else - asm volatile( - "mov r1, %0\n" - "ldm r1!, {r0, r2, r4, r5, r6, r7}\n" - "mov sp, r2\n" - "bx r0\n" - : - : "l" (&jmp->target) - : "r1"); + u32 regs[10]; /* r4-r9, sl, fp, sp, lr */ #endif +}; - while (1) { } -} +typedef struct jmp_buf_data jmp_buf[1]; +int setjmp(jmp_buf jmp); +void longjmp(jmp_buf jmp, int ret); #endif /* _SETJMP_H_ */ diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile index 6e1c4369334..abffa10c850 100644 --- a/arch/arm/lib/Makefile +++ b/arch/arm/lib/Makefile @@ -17,6 +17,12 @@ else obj-y += vectors.o crt0.o endif +ifdef CONFIG_ARM64 +obj-y += setjmp_aarch64.o +else +obj-y += setjmp.o +endif + ifndef CONFIG_SPL_BUILD ifdef CONFIG_ARM64 obj-y += relocate_64.o diff --git a/arch/arm/lib/setjmp.S b/arch/arm/lib/setjmp.S new file mode 100644 index 00000000000..6746e5e2cc4 --- /dev/null +++ b/arch/arm/lib/setjmp.S @@ -0,0 +1,37 @@ +/* + * (C) 2017 Theobroma Systems Design und Consulting GmbH + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include + +.pushsection .text.setjmp, "ax" +ENTRY(setjmp) + /* + * A subroutine must preserve the contents of the registers + * r4-r8, r10, r11 (v1-v5, v7 and v8) and SP (and r9 in PCS + * variants that designate r9 as v6). + */ + mov ip, sp + stm a1, {v1-v8, ip, lr} + mov a1, #0 + bx lr +ENDPROC(setjmp) +.popsection + +.pushsection .text.longjmp, "ax" +ENTRY(longjmp) + ldm a1, {v1-v8, ip, lr} + mov sp, ip + mov a1, a2 + /* If we were passed a return value of zero, return one instead */ + cmp a1, #0 + bne 1f + mov a1, #1 +1: + bx lr +ENDPROC(longjmp) +.popsection diff --git a/arch/arm/lib/setjmp_aarch64.S b/arch/arm/lib/setjmp_aarch64.S new file mode 100644 index 00000000000..b68edb86d69 --- /dev/null +++ b/arch/arm/lib/setjmp_aarch64.S @@ -0,0 +1,42 @@ +/* + * (C) 2017 Theobroma Systems Design und Consulting GmbH + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include + +.pushsection .text.setjmp, "ax" +ENTRY(setjmp) + /* Preserve all callee-saved registers and the SP */ + stp x19, x20, [x0,#0] + stp x21, x22, [x0,#16] + stp x23, x24, [x0,#32] + stp x25, x26, [x0,#48] + stp x27, x28, [x0,#64] + stp x29, x30, [x0,#80] + mov x2, sp + str x2, [x0, #96] + mov x0, #0 + ret +ENDPROC(setjmp) +.popsection + +.pushsection .text.longjmp, "ax" +ENTRY(longjmp) + ldp x19, x20, [x0,#0] + ldp x21, x22, [x0,#16] + ldp x23, x24, [x0,#32] + ldp x25, x26, [x0,#48] + ldp x27, x28, [x0,#64] + ldp x29, x30, [x0,#80] + ldr x2, [x0,#96] + mov sp, x2 + /* Move the return value in place, but return 1 if passed 0. */ + adds x0, xzr, x1 + csinc x0, x0, xzr, ne + ret +ENDPROC(longjmp) +.popsection -- cgit v1.3.1 From ecfd71891a81b2db0aada07306e8bc54b4273179 Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Tue, 10 Oct 2017 16:21:14 +0200 Subject: rockchip: back-to-bootrom: replace assembly-implementation with C-code The back-to-bootrom implementation for Rockchip has always relied on the stack-pointer being valid on entry, so there was little reason to have this as an assembly implementation. This provides a new C-only implementation of save_boot_params and back_to_bootrom (relying on setjmp/longjmp) and removes the older assembly-only implementation. Signed-off-by: Philipp Tomsich Tested-by: Andy Yan --- arch/arm/include/asm/arch-rockchip/bootrom.h | 27 ++++++++--- arch/arm/mach-rockchip/Makefile | 4 +- arch/arm/mach-rockchip/bootrom.c | 52 ++++++++++++++++++++- arch/arm/mach-rockchip/save_boot_param.S | 69 ---------------------------- 4 files changed, 73 insertions(+), 79 deletions(-) delete mode 100644 arch/arm/mach-rockchip/save_boot_param.S (limited to 'arch') diff --git a/arch/arm/include/asm/arch-rockchip/bootrom.h b/arch/arm/include/asm/arch-rockchip/bootrom.h index 169cc5e50b0..2f61a338116 100644 --- a/arch/arm/include/asm/arch-rockchip/bootrom.h +++ b/arch/arm/include/asm/arch-rockchip/bootrom.h @@ -1,5 +1,6 @@ /* * (C) Copyright 2017 Heiko Stuebner + * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH * * SPDX-License-Identifier: GPL-2.0 */ @@ -14,15 +15,27 @@ extern u32 SAVE_SP_ADDR; /** - * Hand control back to the bootrom to load another - * boot stage. + * back_to_bootrom() - return to bootrom (for TPL/SPL), passing a + * result code + * + * Transfer control back to the Rockchip BROM, restoring necessary + * register context and passing a command/result code to the BROM + * to instruct its next actions (e.g. continue boot sequence, enter + * download mode, ...). + * + * This function does not return. */ -void back_to_bootrom(void); +enum rockchip_bootrom_cmd { + /* + * These can not start at 0, as 0 has a special meaning + * for setjmp(). + */ -/** - * Assembler component for the above (do not call this directly) - */ -void _back_to_bootrom_s(void); + BROM_BOOT_NEXTSTAGE = 1, /* continue boot-sequence */ + BROM_BOOT_ENTER_DNL, /* have BROM enter download-mode */ +}; + +void back_to_bootrom(void); /** * Boot-device identifiers as used by the BROM diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile index daafc8de6a8..b875dfc6b0d 100644 --- a/arch/arm/mach-rockchip/Makefile +++ b/arch/arm/mach-rockchip/Makefile @@ -8,8 +8,8 @@ # this may have entered from ATF with the stack-pointer pointing to # inaccessible/protected memory (and the bootrom-helper assumes that # the stack-pointer is valid before switching to the U-Boot stack). -obj-spl-$(CONFIG_ROCKCHIP_BROM_HELPER) += bootrom.o save_boot_param.o -obj-tpl-$(CONFIG_ROCKCHIP_BROM_HELPER) += bootrom.o save_boot_param.o +obj-spl-$(CONFIG_ROCKCHIP_BROM_HELPER) += bootrom.o +obj-tpl-$(CONFIG_ROCKCHIP_BROM_HELPER) += bootrom.o obj-tpl-$(CONFIG_ROCKCHIP_RK3188) += rk3188-board-tpl.o obj-tpl-$(CONFIG_ROCKCHIP_RK3288) += rk3288-board-tpl.o diff --git a/arch/arm/mach-rockchip/bootrom.c b/arch/arm/mach-rockchip/bootrom.c index 8380e4e0061..7b9b307a89c 100644 --- a/arch/arm/mach-rockchip/bootrom.c +++ b/arch/arm/mach-rockchip/bootrom.c @@ -6,11 +6,61 @@ #include #include +#include +#include + +/* + * Force the jmp_buf to the data-section, as .bss will not be valid + * when save_boot_params is invoked. + */ +static jmp_buf brom_ctx __section(".data"); void back_to_bootrom(void) { #if CONFIG_IS_ENABLED(LIBCOMMON_SUPPORT) puts("Returning to boot ROM...\n"); #endif - _back_to_bootrom_s(); + longjmp(brom_ctx, BROM_BOOT_NEXTSTAGE); +} + +/* + * All Rockchip BROM implementations enter with a valid stack-pointer, + * so this can safely be implemented in C (providing a single + * implementation both for ARMv7 and AArch64). + */ +int save_boot_params(void) +{ + int ret = setjmp(brom_ctx); + + switch (ret) { + case 0: + /* + * This is the initial pass through this function + * (i.e. saving the context), setjmp just setup up the + * brom_ctx: transfer back into the startup-code at + * 'save_boot_params_ret' and let the compiler know + * that this will not return. + */ + save_boot_params_ret(); + while (true) + /* does not return */; + break; + + case BROM_BOOT_NEXTSTAGE: + /* + * To instruct the BROM to boot the next stage, we + * need to return 0 to it: i.e. we need to rewrite + * the return code once more. + */ + ret = 0; + break; + + default: +#if CONFIG_IS_ENABLED(LIBCOMMON_SUPPORT) + puts("FATAL: unexpected command to back_to_bootrom()\n"); +#endif + hang(); + }; + + return ret; } diff --git a/arch/arm/mach-rockchip/save_boot_param.S b/arch/arm/mach-rockchip/save_boot_param.S deleted file mode 100644 index 50fce207a53..00000000000 --- a/arch/arm/mach-rockchip/save_boot_param.S +++ /dev/null @@ -1,69 +0,0 @@ -/* - * (C) Copyright 2016 Rockchip Electronics Co., Ltd - * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include - -#if defined(CONFIG_ARM64) -.globl SAVE_SP_ADDR -SAVE_SP_ADDR: - .quad 0 - -ENTRY(save_boot_params) - sub sp, sp, #0x60 - stp x29, x30, [sp, #0x50] - stp x27, x28, [sp, #0x40] - stp x25, x26, [sp, #0x30] - stp x23, x24, [sp, #0x20] - stp x21, x22, [sp, #0x10] - stp x19, x20, [sp, #0] - ldr x8, =SAVE_SP_ADDR - mov x9, sp - str x9, [x8] - b save_boot_params_ret /* back to my caller */ -ENDPROC(save_boot_params) - -.globl _back_to_bootrom_s -ENTRY(_back_to_bootrom_s) - ldr x0, =SAVE_SP_ADDR - ldr x0, [x0] - mov sp, x0 - ldp x29, x30, [sp, #0x50] - ldp x27, x28, [sp, #0x40] - ldp x25, x26, [sp, #0x30] - ldp x23, x24, [sp, #0x20] - ldp x21, x22, [sp, #0x10] - ldp x19, x20, [sp] - add sp, sp, #0x60 - mov x0, xzr - ret -ENDPROC(_back_to_bootrom_s) -#else -.globl SAVE_SP_ADDR -SAVE_SP_ADDR: - .word 0 - -/* - * void save_boot_params - * - * Save sp, lr, r1~r12 - */ -ENTRY(save_boot_params) - push {r1-r12, lr} - ldr r0, =SAVE_SP_ADDR - str sp, [r0] - b save_boot_params_ret @ back to my caller -ENDPROC(save_boot_params) - - -.globl _back_to_bootrom_s -ENTRY(_back_to_bootrom_s) - ldr r0, =SAVE_SP_ADDR - ldr sp, [r0] - mov r0, #0 - pop {r1-r12, pc} -ENDPROC(_back_to_bootrom_s) -#endif -- cgit v1.3.1 From 4d9253fb76f59c6f474ca54fe2d45c5706cd86e3 Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Tue, 10 Oct 2017 16:21:15 +0200 Subject: rockchip: rk3188: use boot0 hook to load up SPL in 2 steps For the RK3188, the BROM will attempt to load up the first stage image (SPL for the RK3188) in two steps: first 1KB to offset 0x800 in the SRAM and then the remainder to offset 0xc00 in the SRAM. It always enters at 0x804, though. With this changeset, the RK3188 boot removes the TPL (stub) stage and builds a single SPL binary that utilizes the early back-to-bootrom via the boot0-hook. Consequently, the passing of the saved boot params via pmu->os_reg[2] is also removed. Signed-off-by: Philipp Tomsich --- arch/arm/mach-rockchip/Kconfig | 2 +- arch/arm/mach-rockchip/Makefile | 1 - arch/arm/mach-rockchip/rk3188-board-spl.c | 10 ---- arch/arm/mach-rockchip/rk3188-board-tpl.c | 86 ------------------------------- doc/README.rockchip | 10 ++-- include/configs/rk3188_common.h | 12 ++--- 6 files changed, 9 insertions(+), 112 deletions(-) delete mode 100644 arch/arm/mach-rockchip/rk3188-board-tpl.c (limited to 'arch') diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig index d59a1d5ccb2..09f2c45954d 100644 --- a/arch/arm/mach-rockchip/Kconfig +++ b/arch/arm/mach-rockchip/Kconfig @@ -18,7 +18,7 @@ config ROCKCHIP_RK3188 select SUPPORT_SPL select SUPPORT_TPL select SPL - select TPL + select SPL_ROCKCHIP_EARLYRETURN_TO_BROM select BOARD_LATE_INIT select ROCKCHIP_BROM_HELPER help diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile index b875dfc6b0d..c15e9bf1348 100644 --- a/arch/arm/mach-rockchip/Makefile +++ b/arch/arm/mach-rockchip/Makefile @@ -11,7 +11,6 @@ obj-spl-$(CONFIG_ROCKCHIP_BROM_HELPER) += bootrom.o obj-tpl-$(CONFIG_ROCKCHIP_BROM_HELPER) += bootrom.o -obj-tpl-$(CONFIG_ROCKCHIP_RK3188) += rk3188-board-tpl.o obj-tpl-$(CONFIG_ROCKCHIP_RK3288) += rk3288-board-tpl.o obj-tpl-$(CONFIG_ROCKCHIP_RK3368) += rk3368-board-tpl.o diff --git a/arch/arm/mach-rockchip/rk3188-board-spl.c b/arch/arm/mach-rockchip/rk3188-board-spl.c index 406207ed21c..05d4ae682f7 100644 --- a/arch/arm/mach-rockchip/rk3188-board-spl.c +++ b/arch/arm/mach-rockchip/rk3188-board-spl.c @@ -101,7 +101,6 @@ static int setup_arm_clock(void) void board_init_f(ulong dummy) { struct udevice *pinctrl, *dev; - struct rk3188_pmu *pmu; int ret; /* Example code showing how to enable the debug UART on RK3188 */ @@ -145,15 +144,6 @@ void board_init_f(ulong dummy) return; } - /* - * Recover the bootrom's stackpointer. - * For whatever reason needs to run after rockchip_get_clk. - */ - pmu = syscon_get_first_range(ROCKCHIP_SYSCON_PMU); - if (IS_ERR(pmu)) - pr_err("pmu syscon returned %ld\n", PTR_ERR(pmu)); - SAVE_SP_ADDR = readl(&pmu->sys_reg[2]); - ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl); if (ret) { debug("Pinctrl init failed: %d\n", ret); diff --git a/arch/arm/mach-rockchip/rk3188-board-tpl.c b/arch/arm/mach-rockchip/rk3188-board-tpl.c deleted file mode 100644 index b458ef6ea8b..00000000000 --- a/arch/arm/mach-rockchip/rk3188-board-tpl.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * (C) Copyright 2015 Google, Inc - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include -#include - -DECLARE_GLOBAL_DATA_PTR; - -/* track how often we were entered */ -static int rk3188_num_entries __attribute__ ((section(".data"))); - -#define PMU_BASE 0x20004000 -#define SPL_ENTRY 0x10080C00 - -static void jump_to_spl(void) -{ - typedef void __noreturn (*image_entry_noargs_t)(void); - - struct rk3188_pmu * const pmu = (void *)PMU_BASE; - image_entry_noargs_t tpl_entry = - (image_entry_noargs_t)(unsigned long)SPL_ENTRY; - - /* Store the SAVE_SP_ADDR in a location shared with SPL. */ - writel(SAVE_SP_ADDR, &pmu->sys_reg[2]); - tpl_entry(); -} - -void board_init_f(ulong dummy) -{ - /* Example code showing how to enable the debug UART on RK3188 */ -#ifdef EARLY_UART -#include - /* Enable early UART on the RK3188 */ -#define GRF_BASE 0x20008000 - struct rk3188_grf * const grf = (void *)GRF_BASE; - - rk_clrsetreg(&grf->gpio1b_iomux, - GPIO1B1_MASK << GPIO1B1_SHIFT | - GPIO1B0_MASK << GPIO1B0_SHIFT, - GPIO1B1_UART2_SOUT << GPIO1B1_SHIFT | - GPIO1B0_UART2_SIN << GPIO1B0_SHIFT); - /* - * Debug UART can be used from here if required: - * - * debug_uart_init(); - * printch('a'); - * printhex8(0x1234); - * printascii("string"); - */ - debug_uart_init(); - - printch('t'); - printch('p'); - printch('l'); - printch('-'); - printch(rk3188_num_entries + 1 + '0'); - printch('\n'); -#endif - - rk3188_num_entries++; - - if (rk3188_num_entries == 1) { - /* - * The original loader did some very basic integrity - * checking at this point, but the remaining few bytes - * could be used for any improvement making sense - * really early on. - */ - - back_to_bootrom(); - } else { - /* - * TPL part of the loader should now wait for us - * at offset 0xC00 in the sram. Should never return - * from there. - */ - jump_to_spl(); - } -} diff --git a/doc/README.rockchip b/doc/README.rockchip index da99f301ff7..597f068aca6 100644 --- a/doc/README.rockchip +++ b/doc/README.rockchip @@ -176,17 +176,17 @@ described above, but the image creation needs a bit more care. The bootrom of rk3188 expects to find a small 1kb loader which returns control to the bootrom, after which it will load the real loader, which -can then be up to 29kb in size and does the regular ddr init. +can then be up to 29kb in size and does the regular ddr init. This is +handled by a single image (built as the SPL stage) that tests whether +it is handled for the first or second time via code executed from the +boot0-hook. Additionally the rk3188 requires everything the bootrom loads to be rc4-encrypted. Except for the very first stage the bootrom always reads and decodes 2kb pages, so files should be sized accordingly. # copy tpl, pad to 1020 bytes and append spl -cat tpl/u-boot-tpl.bin > tplspl.bin -truncate -s 1020 tplspl.bin -cat spl/u-boot-spl.bin >> tplspl.bin -tools/mkimage -n rk3188 -T rksd -d tplspl.bin out +tools/mkimage -n rk3188 -T rksd -d spl/u-boot-spl.bin out # truncate, encode and append u-boot.bin truncate -s %2048 u-boot.bin diff --git a/include/configs/rk3188_common.h b/include/configs/rk3188_common.h index cfa53647102..68a42a95d94 100644 --- a/include/configs/rk3188_common.h +++ b/include/configs/rk3188_common.h @@ -36,14 +36,9 @@ #define CONFIG_ROCKCHIP_MAX_INIT_SIZE (0x8000 - 0x800) #define CONFIG_ROCKCHIP_CHIP_TAG "RK31" -#ifdef CONFIG_TPL_BUILD -#define CONFIG_SPL_TEXT_BASE 0x10080804 -/* tpl size 1kb - 4byte RK31 header */ -#define CONFIG_SPL_MAX_SIZE (0x400 - 0x4) -#elif defined(CONFIG_SPL_BUILD) -/* spl size 32kb sram - 2kb bootrom - 1kb spl */ -#define CONFIG_SPL_MAX_SIZE (0x8000 - 0xC00) -#define CONFIG_SPL_TEXT_BASE 0x10080C00 +#define CONFIG_SPL_TEXT_BASE 0x10080800 +/* spl size 32kb sram - 2kb bootrom */ +#define CONFIG_SPL_MAX_SIZE (0x8000 - 0x800) #define CONFIG_SPL_FRAMEWORK 1 #define CONFIG_SPL_CLK 1 #define CONFIG_SPL_PINCTRL 1 @@ -52,7 +47,6 @@ #define CONFIG_SPL_RAM 1 #define CONFIG_SPL_DRIVERS_MISC_SUPPORT 1 #define CONFIG_ROCKCHIP_SERIAL 1 -#endif #define CONFIG_SPL_STACK 0x10087fff -- cgit v1.3.1 From b82bd1f8d41e06706447a9a26aabf0bd45a90b74 Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Tue, 10 Oct 2017 16:21:16 +0200 Subject: rockchip: back-to-bootrom: allow passing a cmd to the bootrom The BROM supports forcing it to enter download-mode, if an appropriate result/cmd-word is returned to it. There already is a series to support this in review, so this prepares the (newly C-version) of the back-to-bootrom code to accept a cmd to passed on to the BROM. All the existing call-sites are adjusted to match the changed function signature. Signed-off-by: Philipp Tomsich Tested-by: Andy Yan --- arch/arm/include/asm/arch-rockchip/bootrom.h | 5 ++++- arch/arm/mach-rockchip/bootrom.c | 4 ++-- arch/arm/mach-rockchip/rk3036-board-spl.c | 2 +- arch/arm/mach-rockchip/rk3188-board-spl.c | 4 ++-- arch/arm/mach-rockchip/rk322x-board-spl.c | 2 +- arch/arm/mach-rockchip/rk3288-board-spl.c | 4 ++-- arch/arm/mach-rockchip/rk3288-board-tpl.c | 2 +- arch/arm/mach-rockchip/rk3368-board-tpl.c | 2 +- arch/arm/mach-rockchip/rk3399-board-spl.c | 2 +- 9 files changed, 15 insertions(+), 12 deletions(-) (limited to 'arch') diff --git a/arch/arm/include/asm/arch-rockchip/bootrom.h b/arch/arm/include/asm/arch-rockchip/bootrom.h index 2f61a338116..103b7995939 100644 --- a/arch/arm/include/asm/arch-rockchip/bootrom.h +++ b/arch/arm/include/asm/arch-rockchip/bootrom.h @@ -24,6 +24,9 @@ extern u32 SAVE_SP_ADDR; * download mode, ...). * * This function does not return. + * + * @brom_cmd: indicates how the bootrom should continue the boot + * sequence (e.g. load the next stage) */ enum rockchip_bootrom_cmd { /* @@ -35,7 +38,7 @@ enum rockchip_bootrom_cmd { BROM_BOOT_ENTER_DNL, /* have BROM enter download-mode */ }; -void back_to_bootrom(void); +void back_to_bootrom(enum rockchip_bootrom_cmd brom_cmd); /** * Boot-device identifiers as used by the BROM diff --git a/arch/arm/mach-rockchip/bootrom.c b/arch/arm/mach-rockchip/bootrom.c index 7b9b307a89c..e369fdc25a8 100644 --- a/arch/arm/mach-rockchip/bootrom.c +++ b/arch/arm/mach-rockchip/bootrom.c @@ -15,12 +15,12 @@ */ static jmp_buf brom_ctx __section(".data"); -void back_to_bootrom(void) +void back_to_bootrom(enum rockchip_bootrom_cmd brom_cmd) { #if CONFIG_IS_ENABLED(LIBCOMMON_SUPPORT) puts("Returning to boot ROM...\n"); #endif - longjmp(brom_ctx, BROM_BOOT_NEXTSTAGE); + longjmp(brom_ctx, brom_cmd); } /* diff --git a/arch/arm/mach-rockchip/rk3036-board-spl.c b/arch/arm/mach-rockchip/rk3036-board-spl.c index 9458201bd39..550e3a15214 100644 --- a/arch/arm/mach-rockchip/rk3036-board-spl.c +++ b/arch/arm/mach-rockchip/rk3036-board-spl.c @@ -40,7 +40,7 @@ void board_init_f(ulong dummy) sdram_init(); /* return to maskrom */ - back_to_bootrom(); + back_to_bootrom(BROM_BOOT_NEXTSTAGE); } /* Place Holders */ diff --git a/arch/arm/mach-rockchip/rk3188-board-spl.c b/arch/arm/mach-rockchip/rk3188-board-spl.c index 05d4ae682f7..8e3b8ae3baf 100644 --- a/arch/arm/mach-rockchip/rk3188-board-spl.c +++ b/arch/arm/mach-rockchip/rk3188-board-spl.c @@ -158,7 +158,7 @@ void board_init_f(ulong dummy) setup_arm_clock(); #if CONFIG_IS_ENABLED(ROCKCHIP_BACK_TO_BROM) && !defined(CONFIG_SPL_BOARD_INIT) - back_to_bootrom(); + back_to_bootrom(BROM_BOOT_NEXTSTAGE); #endif } @@ -219,7 +219,7 @@ void spl_board_init(void) preloader_console_init(); #if CONFIG_IS_ENABLED(ROCKCHIP_BACK_TO_BROM) - back_to_bootrom(); + back_to_bootrom(BROM_BOOT_NEXTSTAGE); #endif return; diff --git a/arch/arm/mach-rockchip/rk322x-board-spl.c b/arch/arm/mach-rockchip/rk322x-board-spl.c index 4ddb8ba065f..35f4f978c4e 100644 --- a/arch/arm/mach-rockchip/rk322x-board-spl.c +++ b/arch/arm/mach-rockchip/rk322x-board-spl.c @@ -76,6 +76,6 @@ void board_init_f(ulong dummy) /* Disable the ddr secure region setting to make it non-secure */ rk_clrreg(SGRF_DDR_CON0, 0x4000); #if defined(CONFIG_ROCKCHIP_SPL_BACK_TO_BROM) && !defined(CONFIG_SPL_BOARD_INIT) - back_to_bootrom(); + back_to_bootrom(BROM_BOOT_NEXTSTAGE); #endif } diff --git a/arch/arm/mach-rockchip/rk3288-board-spl.c b/arch/arm/mach-rockchip/rk3288-board-spl.c index 7b7fd5a6f1a..f64a54843f7 100644 --- a/arch/arm/mach-rockchip/rk3288-board-spl.c +++ b/arch/arm/mach-rockchip/rk3288-board-spl.c @@ -216,7 +216,7 @@ void board_init_f(ulong dummy) #endif #if CONFIG_IS_ENABLED(ROCKCHIP_BACK_TO_BROM) && !defined(CONFIG_SPL_BOARD_INIT) - back_to_bootrom(); + back_to_bootrom(BROM_BOOT_NEXTSTAGE); #endif } @@ -283,7 +283,7 @@ void spl_board_init(void) preloader_console_init(); #if CONFIG_IS_ENABLED(ROCKCHIP_BACK_TO_BROM) - back_to_bootrom(); + back_to_bootrom(BROM_BOOT_NEXTSTAGE); #endif return; err: diff --git a/arch/arm/mach-rockchip/rk3288-board-tpl.c b/arch/arm/mach-rockchip/rk3288-board-tpl.c index 3d08b5b6d8d..150beea02e1 100644 --- a/arch/arm/mach-rockchip/rk3288-board-tpl.c +++ b/arch/arm/mach-rockchip/rk3288-board-tpl.c @@ -69,7 +69,7 @@ void board_init_f(ulong dummy) void board_return_to_bootrom(void) { - back_to_bootrom(); + back_to_bootrom(BROM_BOOT_NEXTSTAGE); } u32 spl_boot_device(void) diff --git a/arch/arm/mach-rockchip/rk3368-board-tpl.c b/arch/arm/mach-rockchip/rk3368-board-tpl.c index b3e6ffa781b..60d5aeade99 100644 --- a/arch/arm/mach-rockchip/rk3368-board-tpl.c +++ b/arch/arm/mach-rockchip/rk3368-board-tpl.c @@ -148,7 +148,7 @@ void board_init_f(ulong dummy) void board_return_to_bootrom(void) { - back_to_bootrom(); + back_to_bootrom(BROM_BOOT_NEXTSTAGE); } u32 spl_boot_device(void) diff --git a/arch/arm/mach-rockchip/rk3399-board-spl.c b/arch/arm/mach-rockchip/rk3399-board-spl.c index 9c20f56dc94..b96903e70fa 100644 --- a/arch/arm/mach-rockchip/rk3399-board-spl.c +++ b/arch/arm/mach-rockchip/rk3399-board-spl.c @@ -23,7 +23,7 @@ DECLARE_GLOBAL_DATA_PTR; void board_return_to_bootrom(void) { - back_to_bootrom(); + back_to_bootrom(BROM_BOOT_NEXTSTAGE); } static const char * const boot_devices[BROM_LAST_BOOTSOURCE + 1] = { -- cgit v1.3.1 From 4bbb05bcb505f347fab383bbfb40d126fd1c5096 Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Tue, 10 Oct 2017 16:21:17 +0200 Subject: rockchip: rk3188: move CONFIG_SPL_* entries from rk3188_common.h to Kconfig There still are a few CONFIG_SPL_* options selected using defines from rk3188_common.h instead of via Kconfig. This migrates those over to Kconfig. Signed-off-by: Philipp Tomsich --- arch/arm/mach-rockchip/Kconfig | 7 ++++++- include/configs/rk3188_common.h | 6 ------ 2 files changed, 6 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig index 09f2c45954d..36df484b5ee 100644 --- a/arch/arm/mach-rockchip/Kconfig +++ b/arch/arm/mach-rockchip/Kconfig @@ -16,8 +16,13 @@ config ROCKCHIP_RK3188 select CPU_V7 select SPL_BOARD_INIT if SPL select SUPPORT_SPL - select SUPPORT_TPL select SPL + select SPL_CLK + select SPL_PINCTRL + select SPL_REGMAP + select SPL_SYSCON + select SPL_RAM + select SPL_DRIVERS_MISC_SUPPORT select SPL_ROCKCHIP_EARLYRETURN_TO_BROM select BOARD_LATE_INIT select ROCKCHIP_BROM_HELPER diff --git a/include/configs/rk3188_common.h b/include/configs/rk3188_common.h index 68a42a95d94..0cb0762345e 100644 --- a/include/configs/rk3188_common.h +++ b/include/configs/rk3188_common.h @@ -40,12 +40,6 @@ /* spl size 32kb sram - 2kb bootrom */ #define CONFIG_SPL_MAX_SIZE (0x8000 - 0x800) #define CONFIG_SPL_FRAMEWORK 1 -#define CONFIG_SPL_CLK 1 -#define CONFIG_SPL_PINCTRL 1 -#define CONFIG_SPL_REGMAP 1 -#define CONFIG_SPL_SYSCON 1 -#define CONFIG_SPL_RAM 1 -#define CONFIG_SPL_DRIVERS_MISC_SUPPORT 1 #define CONFIG_ROCKCHIP_SERIAL 1 #define CONFIG_SPL_STACK 0x10087fff -- cgit v1.3.1 From 6ba54058ed6e5b5d7fb14b99a0d9f803ef83b1d3 Mon Sep 17 00:00:00 2001 From: Kever Yang Date: Fri, 3 Nov 2017 15:16:12 +0800 Subject: rockchip: sysreset: merge into one common driver Use a common driver for all Rockchip SOC instead of one for each SoC. Use driver_data for reg offset. Signed-off-by: Kever Yang Acked-by: Philipp Tomsich Acked-by: Philipp Tomsich Reviewed-by: Philipp Tomsich --- arch/arm/include/asm/arch-rockchip/clock.h | 5 +++ drivers/sysreset/sysreset_rk3036.c | 45 ---------------------- drivers/sysreset/sysreset_rk3188.c | 62 ------------------------------ drivers/sysreset/sysreset_rk322x.c | 45 ---------------------- drivers/sysreset/sysreset_rk3288.c | 47 ---------------------- drivers/sysreset/sysreset_rk3328.c | 45 ---------------------- drivers/sysreset/sysreset_rk3368.c | 62 ------------------------------ drivers/sysreset/sysreset_rk3399.c | 45 ---------------------- drivers/sysreset/sysreset_rockchip.c | 47 ++++++++++++++++++++++ drivers/sysreset/sysreset_rv1108.c | 46 ---------------------- 10 files changed, 52 insertions(+), 397 deletions(-) delete mode 100644 drivers/sysreset/sysreset_rk3036.c delete mode 100644 drivers/sysreset/sysreset_rk3188.c delete mode 100644 drivers/sysreset/sysreset_rk322x.c delete mode 100644 drivers/sysreset/sysreset_rk3288.c delete mode 100644 drivers/sysreset/sysreset_rk3328.c delete mode 100644 drivers/sysreset/sysreset_rk3368.c delete mode 100644 drivers/sysreset/sysreset_rk3399.c create mode 100644 drivers/sysreset/sysreset_rockchip.c delete mode 100644 drivers/sysreset/sysreset_rv1108.c (limited to 'arch') diff --git a/arch/arm/include/asm/arch-rockchip/clock.h b/arch/arm/include/asm/arch-rockchip/clock.h index 641df58ac25..736b2603fda 100644 --- a/arch/arm/include/asm/arch-rockchip/clock.h +++ b/arch/arm/include/asm/arch-rockchip/clock.h @@ -39,6 +39,11 @@ static inline int rk_pll_id(enum rk_clk_id clk_id) return clk_id - 1; } +struct sysreset_reg { + unsigned int glb_srst_fst_value; + unsigned int glb_srst_snd_value; +}; + /** * clk_get_divisor() - Calculate the required clock divisior * diff --git a/drivers/sysreset/sysreset_rk3036.c b/drivers/sysreset/sysreset_rk3036.c deleted file mode 100644 index b3d21132399..00000000000 --- a/drivers/sysreset/sysreset_rk3036.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * (C) Copyright 2015 Rockchip Electronics Co., Ltd - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -int rk3036_sysreset_request(struct udevice *dev, enum sysreset_t type) -{ - struct rk3036_cru *cru = rockchip_get_cru(); - - if (IS_ERR(cru)) - return PTR_ERR(cru); - switch (type) { - case SYSRESET_WARM: - writel(0xeca8, &cru->cru_glb_srst_snd_value); - break; - case SYSRESET_COLD: - writel(0xfdb9, &cru->cru_glb_srst_fst_value); - break; - default: - return -EPROTONOSUPPORT; - } - - return -EINPROGRESS; -} - -static struct sysreset_ops rk3036_sysreset = { - .request = rk3036_sysreset_request, -}; - -U_BOOT_DRIVER(sysreset_rk3036) = { - .name = "rk3036_sysreset", - .id = UCLASS_SYSRESET, - .ops = &rk3036_sysreset, -}; diff --git a/drivers/sysreset/sysreset_rk3188.c b/drivers/sysreset/sysreset_rk3188.c deleted file mode 100644 index 053a6344f53..00000000000 --- a/drivers/sysreset/sysreset_rk3188.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * (C) Copyright 2015 Google, Inc - * - * SPDX-License-Identifier: GPL-2.0 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -int rk3188_sysreset_request(struct udevice *dev, enum sysreset_t type) -{ - struct rk3188_cru *cru = rockchip_get_cru(); - struct rk3188_grf *grf; - - if (IS_ERR(cru)) - return PTR_ERR(cru); - switch (type) { - case SYSRESET_WARM: - grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); - if (IS_ERR(grf)) - return -EPROTONOSUPPORT; - - /* - * warm-reset keeps the remap value, - * so make sure it's disabled. - */ - rk_clrsetreg(&grf->soc_con0, - NOC_REMAP_MASK << NOC_REMAP_SHIFT, - 0 << NOC_REMAP_SHIFT); - - rk_clrreg(&cru->cru_mode_con, 0xffff); - writel(0xeca8, &cru->cru_glb_srst_snd_value); - break; - case SYSRESET_COLD: - rk_clrreg(&cru->cru_mode_con, 0xffff); - writel(0xfdb9, &cru->cru_glb_srst_fst_value); - break; - default: - return -EPROTONOSUPPORT; - } - - return -EINPROGRESS; -} - -static struct sysreset_ops rk3188_sysreset = { - .request = rk3188_sysreset_request, -}; - -U_BOOT_DRIVER(sysreset_rk3188) = { - .name = "rk3188_sysreset", - .id = UCLASS_SYSRESET, - .ops = &rk3188_sysreset, -}; diff --git a/drivers/sysreset/sysreset_rk322x.c b/drivers/sysreset/sysreset_rk322x.c deleted file mode 100644 index 5fce79b685f..00000000000 --- a/drivers/sysreset/sysreset_rk322x.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * (C) Copyright 2017 Rockchip Electronics Co., Ltd - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -int rk322x_sysreset_request(struct udevice *dev, enum sysreset_t type) -{ - struct rk322x_cru *cru = rockchip_get_cru(); - - if (IS_ERR(cru)) - return PTR_ERR(cru); - switch (type) { - case SYSRESET_WARM: - writel(0xeca8, &cru->cru_glb_srst_snd_value); - break; - case SYSRESET_COLD: - writel(0xfdb9, &cru->cru_glb_srst_fst_value); - break; - default: - return -EPROTONOSUPPORT; - } - - return -EINPROGRESS; -} - -static struct sysreset_ops rk322x_sysreset = { - .request = rk322x_sysreset_request, -}; - -U_BOOT_DRIVER(sysreset_rk322x) = { - .name = "rk322x_sysreset", - .id = UCLASS_SYSRESET, - .ops = &rk322x_sysreset, -}; diff --git a/drivers/sysreset/sysreset_rk3288.c b/drivers/sysreset/sysreset_rk3288.c deleted file mode 100644 index 0aad1c21601..00000000000 --- a/drivers/sysreset/sysreset_rk3288.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * (C) Copyright 2015 Google, Inc - * - * SPDX-License-Identifier: GPL-2.0 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -int rk3288_sysreset_request(struct udevice *dev, enum sysreset_t type) -{ - struct rk3288_cru *cru = rockchip_get_cru(); - - if (IS_ERR(cru)) - return PTR_ERR(cru); - switch (type) { - case SYSRESET_WARM: - rk_clrreg(&cru->cru_mode_con, 0xffff); - writel(0xeca8, &cru->cru_glb_srst_snd_value); - break; - case SYSRESET_COLD: - rk_clrreg(&cru->cru_mode_con, 0xffff); - writel(0xfdb9, &cru->cru_glb_srst_fst_value); - break; - default: - return -EPROTONOSUPPORT; - } - - return -EINPROGRESS; -} - -static struct sysreset_ops rk3288_sysreset = { - .request = rk3288_sysreset_request, -}; - -U_BOOT_DRIVER(sysreset_rk3288) = { - .name = "rk3288_sysreset", - .id = UCLASS_SYSRESET, - .ops = &rk3288_sysreset, -}; diff --git a/drivers/sysreset/sysreset_rk3328.c b/drivers/sysreset/sysreset_rk3328.c deleted file mode 100644 index 7b9af0925b1..00000000000 --- a/drivers/sysreset/sysreset_rk3328.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * (C) Copyright 2016 Rockchip Electronics Co., Ltd - * - * SPDX-License-Identifier: GPL-2.0 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -int rk3328_sysreset_request(struct udevice *dev, enum sysreset_t type) -{ - struct rk3328_cru *cru = rockchip_get_cru(); - - if (IS_ERR(cru)) - return PTR_ERR(cru); - switch (type) { - case SYSRESET_WARM: - writel(0xeca8, &cru->glb_srst_snd_value); - break; - case SYSRESET_COLD: - writel(0xfdb9, &cru->glb_srst_fst_value); - break; - default: - return -EPROTONOSUPPORT; - } - - return -EINPROGRESS; -} - -static struct sysreset_ops rk3328_sysreset = { - .request = rk3328_sysreset_request, -}; - -U_BOOT_DRIVER(sysreset_rk3328) = { - .name = "rk3328_sysreset", - .id = UCLASS_SYSRESET, - .ops = &rk3328_sysreset, -}; diff --git a/drivers/sysreset/sysreset_rk3368.c b/drivers/sysreset/sysreset_rk3368.c deleted file mode 100644 index de62921b78f..00000000000 --- a/drivers/sysreset/sysreset_rk3368.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * (C) Copyright Rockchip Electronics Co., Ltd - * - * SPDX-License-Identifier: GPL-2.0 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static void rk3368_pll_enter_slow_mode(struct rk3368_cru *cru) -{ - struct rk3368_pll *pll; - int i; - - for (i = 0; i < 6; i++) { - pll = &cru->pll[i]; - rk_clrreg(&pll->con3, PLL_MODE_MASK); - } -} - -static int rk3368_sysreset_request(struct udevice *dev, enum sysreset_t type) -{ - struct rk3368_cru *cru = rockchip_get_cru(); - - if (IS_ERR(cru)) - return PTR_ERR(cru); - switch (type) { - case SYSRESET_WARM: - rk3368_pll_enter_slow_mode(cru); - rk_clrsetreg(&cru->glb_rst_con, PMU_GLB_SRST_CTRL_MASK, - PMU_RST_BY_SND_GLB_SRST << PMU_GLB_SRST_CTRL_SHIFT); - writel(0xeca8, &cru->glb_srst_snd_val); - break; - case SYSRESET_COLD: - rk3368_pll_enter_slow_mode(cru); - rk_clrsetreg(&cru->glb_rst_con, PMU_GLB_SRST_CTRL_MASK, - PMU_RST_BY_FST_GLB_SRST << PMU_GLB_SRST_CTRL_SHIFT); - writel(0xfdb9, &cru->glb_srst_fst_val); - break; - default: - return -EPROTONOSUPPORT; - } - - return -EINPROGRESS; -} - -static struct sysreset_ops rk3368_sysreset = { - .request = rk3368_sysreset_request, -}; - -U_BOOT_DRIVER(sysreset_rk3368) = { - .name = "rk3368_sysreset", - .id = UCLASS_SYSRESET, - .ops = &rk3368_sysreset, -}; diff --git a/drivers/sysreset/sysreset_rk3399.c b/drivers/sysreset/sysreset_rk3399.c deleted file mode 100644 index 9a555464c66..00000000000 --- a/drivers/sysreset/sysreset_rk3399.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * (C) Copyright 2016 Rockchip Electronics Co., Ltd - * - * SPDX-License-Identifier: GPL-2.0 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -int rk3399_sysreset_request(struct udevice *dev, enum sysreset_t type) -{ - struct rk3399_cru *cru = rockchip_get_cru(); - - if (IS_ERR(cru)) - return PTR_ERR(cru); - switch (type) { - case SYSRESET_WARM: - writel(0xeca8, &cru->glb_srst_snd_value); - break; - case SYSRESET_COLD: - writel(0xfdb9, &cru->glb_srst_fst_value); - break; - default: - return -EPROTONOSUPPORT; - } - - return -EINPROGRESS; -} - -static struct sysreset_ops rk3399_sysreset = { - .request = rk3399_sysreset_request, -}; - -U_BOOT_DRIVER(sysreset_rk3399) = { - .name = "rk3399_sysreset", - .id = UCLASS_SYSRESET, - .ops = &rk3399_sysreset, -}; diff --git a/drivers/sysreset/sysreset_rockchip.c b/drivers/sysreset/sysreset_rockchip.c new file mode 100644 index 00000000000..894975f3fe9 --- /dev/null +++ b/drivers/sysreset/sysreset_rockchip.c @@ -0,0 +1,47 @@ +/* + * (C) Copyright 2017 Rockchip Electronics Co., Ltd + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int rockchip_sysreset_request(struct udevice *dev, enum sysreset_t type) +{ + struct sysreset_reg *offset = dev_get_priv(dev); + unsigned long cru_base = (unsigned long)rockchip_get_cru(); + + if (IS_ERR_VALUE(cru_base)) + return (int)cru_base; + + switch (type) { + case SYSRESET_WARM: + writel(0xeca8, cru_base + offset->glb_srst_snd_value); + break; + case SYSRESET_COLD: + writel(0xfdb9, cru_base + offset->glb_srst_fst_value); + break; + default: + return -EPROTONOSUPPORT; + } + + return -EINPROGRESS; +} + +static struct sysreset_ops rockchip_sysreset = { + .request = rockchip_sysreset_request, +}; + +U_BOOT_DRIVER(sysreset_rockchip) = { + .name = "rockchip_sysreset", + .id = UCLASS_SYSRESET, + .ops = &rockchip_sysreset, +}; diff --git a/drivers/sysreset/sysreset_rv1108.c b/drivers/sysreset/sysreset_rv1108.c deleted file mode 100644 index 9d8e9f7ade3..00000000000 --- a/drivers/sysreset/sysreset_rv1108.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * (C) Copyright 2015 Rockchip Electronics Co., Ltd - * Author: Andy Yan - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -int rv1108_sysreset_request(struct udevice *dev, enum sysreset_t type) -{ - struct rv1108_cru *cru = rockchip_get_cru(); - - if (IS_ERR(cru)) - return PTR_ERR(cru); - - switch (type) { - case SYSRESET_WARM: - writel(0xeca8, &cru->glb_srst_snd_val); - break; - case SYSRESET_COLD: - writel(0xfdb9, &cru->glb_srst_fst_val); - break; - default: - return -EPROTONOSUPPORT; - } - - return -EINPROGRESS; -} - -static struct sysreset_ops rv1108_sysreset = { - .request = rv1108_sysreset_request, -}; - -U_BOOT_DRIVER(sysreset_rv1108) = { - .name = "rv1108_sysreset", - .id = UCLASS_SYSRESET, - .ops = &rv1108_sysreset, -}; -- cgit v1.3.1 From e3067793c3109744a445f692395b9a3bac778e48 Mon Sep 17 00:00:00 2001 From: Andy Yan Date: Wed, 11 Oct 2017 15:00:16 +0800 Subject: rockchip: make boot_mode related codes reused across all platforms setup_boot_mode function use the same logic but different mode register address across all the rockchip platforms, so it's better to make this function reused across all the platforms, and let the mode register address setting from the config file. Signed-off-by: Andy Yan Reviewed-by: Simon Glass Acked-by: Philipp Tomsich Reviewed-by: Philipp Tomsich --- arch/arm/include/asm/arch-rockchip/boot_mode.h | 2 ++ arch/arm/mach-rockchip/Kconfig | 15 ++++++++++++ arch/arm/mach-rockchip/Makefile | 6 +++++ arch/arm/mach-rockchip/boot_mode.c | 33 ++++++++++++++++++++++++++ arch/arm/mach-rockchip/rk3036-board.c | 24 ------------------- arch/arm/mach-rockchip/rk3188-board.c | 1 + arch/arm/mach-rockchip/rk322x-board.c | 24 ------------------- arch/arm/mach-rockchip/rk3288-board.c | 25 ------------------- arch/arm/mach-rockchip/rk3399-board.c | 14 +++++++++++ 9 files changed, 71 insertions(+), 73 deletions(-) create mode 100644 arch/arm/mach-rockchip/boot_mode.c create mode 100644 arch/arm/mach-rockchip/rk3399-board.c (limited to 'arch') diff --git a/arch/arm/include/asm/arch-rockchip/boot_mode.h b/arch/arm/include/asm/arch-rockchip/boot_mode.h index bd65f60bf2b..163b2e7b04d 100644 --- a/arch/arm/include/asm/arch-rockchip/boot_mode.h +++ b/arch/arm/include/asm/arch-rockchip/boot_mode.h @@ -16,4 +16,6 @@ /* enter usb mass storage mode */ #define BOOT_UMS (REBOOT_FLAG + 12) +int setup_boot_mode(void); + #endif diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig index 36df484b5ee..6144057ad45 100644 --- a/arch/arm/mach-rockchip/Kconfig +++ b/arch/arm/mach-rockchip/Kconfig @@ -117,6 +117,7 @@ config ROCKCHIP_RK3399 select SPL_SERIAL_SUPPORT select SPL_DRIVERS_MISC_SUPPORT select DEBUG_UART_BOARD_INIT + select BOARD_LATE_INIT help The Rockchip RK3399 is a ARM-based SoC with a dual-core Cortex-A72 and quad-core Cortex-A53. @@ -152,6 +153,20 @@ config TPL_ROCKCHIP_BACK_TO_BROM SPL will return to the boot rom, which will then load the U-Boot binary to keep going on. +config ROCKCHIP_BOOT_MODE_REG + hex "Rockchip boot mode flag register address" + default 0x200081c8 if ROCKCHIP_RK3036 + default 0x20004040 if ROCKCHIP_RK3188 + default 0x110005c8 if ROCKCHIP_RK322X + default 0xff730094 if ROCKCHIP_RK3288 + default 0xff738200 if ROCKCHIP_RK3368 + default 0xff320300 if ROCKCHIP_RK3399 + default 0x10300580 if ROCKCHIP_RV1108 + default 0 + help + The Soc will enter to different boot mode(defined in asm/arch/boot_mode.h) + according to the value from this register. + config ROCKCHIP_SPL_RESERVE_IRAM hex "Size of IRAM reserved in SPL" default 0x4000 diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile index c15e9bf1348..2127f2bbe80 100644 --- a/arch/arm/mach-rockchip/Makefile +++ b/arch/arm/mach-rockchip/Makefile @@ -22,10 +22,16 @@ obj-spl-$(CONFIG_ROCKCHIP_RK3368) += rk3368-board-spl.o spl-boot-order.o obj-spl-$(CONFIG_ROCKCHIP_RK3399) += rk3399-board-spl.o spl-boot-order.o ifeq ($(CONFIG_SPL_BUILD)$(CONFIG_TPL_BUILD),) + +ifneq ($(CONFIG_ROCKCHIP_BOOT_MODE_REG),0) +obj-y += boot_mode.o +endif + obj-$(CONFIG_ROCKCHIP_RK3188) += rk3188-board.o obj-$(CONFIG_ROCKCHIP_RK322X) += rk322x-board.o obj-$(CONFIG_ROCKCHIP_RK3288) += rk3288-board.o obj-$(CONFIG_ROCKCHIP_RK3036) += rk3036-board.o +obj-$(CONFIG_ROCKCHIP_RK3399) += rk3399-board.o endif obj-$(CONFIG_$(SPL_TPL_)RAM) += sdram_common.o diff --git a/arch/arm/mach-rockchip/boot_mode.c b/arch/arm/mach-rockchip/boot_mode.c new file mode 100644 index 00000000000..46524900def --- /dev/null +++ b/arch/arm/mach-rockchip/boot_mode.c @@ -0,0 +1,33 @@ +/* + * (C) Copyright 2016 Rockchip Electronics Co., Ltd + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include + +int setup_boot_mode(void) +{ + void *reg = (void *)CONFIG_ROCKCHIP_BOOT_MODE_REG; + int boot_mode = readl(reg); + + debug("boot mode %x.\n", boot_mode); + + /* Clear boot mode */ + writel(BOOT_NORMAL, reg); + + switch (boot_mode) { + case BOOT_FASTBOOT: + printf("enter fastboot!\n"); + env_set("preboot", "setenv preboot; fastboot usb0"); + break; + case BOOT_UMS: + printf("enter UMS!\n"); + env_set("preboot", "setenv preboot; ums mmc 0"); + break; + } + + return 0; +} diff --git a/arch/arm/mach-rockchip/rk3036-board.c b/arch/arm/mach-rockchip/rk3036-board.c index a3457f39144..a5d257168f8 100644 --- a/arch/arm/mach-rockchip/rk3036-board.c +++ b/arch/arm/mach-rockchip/rk3036-board.c @@ -19,30 +19,6 @@ DECLARE_GLOBAL_DATA_PTR; -#define GRF_BASE 0x20008000 - -static void setup_boot_mode(void) -{ - struct rk3036_grf *const grf = (void *)GRF_BASE; - int boot_mode = readl(&grf->os_reg[4]); - - debug("boot mode %x.\n", boot_mode); - - /* Clear boot mode */ - writel(BOOT_NORMAL, &grf->os_reg[4]); - - switch (boot_mode) { - case BOOT_FASTBOOT: - printf("enter fastboot!\n"); - env_set("preboot", "setenv preboot; fastboot usb0"); - break; - case BOOT_UMS: - printf("enter UMS!\n"); - env_set("preboot", "setenv preboot; ums mmc 0"); - break; - } -} - __weak int rk_board_late_init(void) { return 0; diff --git a/arch/arm/mach-rockchip/rk3188-board.c b/arch/arm/mach-rockchip/rk3188-board.c index 96859a5b4bc..916d18fc329 100644 --- a/arch/arm/mach-rockchip/rk3188-board.c +++ b/arch/arm/mach-rockchip/rk3188-board.c @@ -24,6 +24,7 @@ int board_late_init(void) { struct rk3188_grf *grf; + setup_boot_mode(); grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); if (IS_ERR(grf)) { pr_err("grf syscon returned %ld\n", PTR_ERR(grf)); diff --git a/arch/arm/mach-rockchip/rk322x-board.c b/arch/arm/mach-rockchip/rk322x-board.c index d44311457a4..e71847de879 100644 --- a/arch/arm/mach-rockchip/rk322x-board.c +++ b/arch/arm/mach-rockchip/rk322x-board.c @@ -16,30 +16,6 @@ DECLARE_GLOBAL_DATA_PTR; -#define GRF_BASE 0x11000000 - -static void setup_boot_mode(void) -{ - struct rk322x_grf *const grf = (void *)GRF_BASE; - int boot_mode = readl(&grf->os_reg[0]); - - debug("boot mode %x.\n", boot_mode); - - /* Clear boot mode */ - writel(BOOT_NORMAL, &grf->os_reg[0]); - - switch (boot_mode) { - case BOOT_FASTBOOT: - printf("enter fastboot!\n"); - env_set("preboot", "setenv preboot; fastboot usb0"); - break; - case BOOT_UMS: - printf("enter UMS!\n"); - env_set("preboot", "setenv preboot; ums mmc 0"); - break; - } -} - __weak int rk_board_late_init(void) { return 0; diff --git a/arch/arm/mach-rockchip/rk3288-board.c b/arch/arm/mach-rockchip/rk3288-board.c index 278bb406f03..1c53ccabacf 100644 --- a/arch/arm/mach-rockchip/rk3288-board.c +++ b/arch/arm/mach-rockchip/rk3288-board.c @@ -23,31 +23,6 @@ DECLARE_GLOBAL_DATA_PTR; -#define PMU_BASE 0xff730000 - -static void setup_boot_mode(void) -{ - struct rk3288_pmu *const pmu = (void *)PMU_BASE; - int boot_mode = readl(&pmu->sys_reg[0]); - - debug("boot mode %x.\n", boot_mode); - - /* Clear boot mode */ - writel(BOOT_NORMAL, &pmu->sys_reg[0]); - - switch (boot_mode) { - case BOOT_FASTBOOT: - printf("enter fastboot!\n"); - env_set("preboot", "setenv preboot; fastboot usb0"); - break; - case BOOT_UMS: - printf("enter UMS!\n"); - env_set("preboot", "setenv preboot; if mmc dev 0;" - "then ums mmc 0; else ums mmc 1;fi"); - break; - } -} - __weak int rk_board_late_init(void) { return 0; diff --git a/arch/arm/mach-rockchip/rk3399-board.c b/arch/arm/mach-rockchip/rk3399-board.c new file mode 100644 index 00000000000..9293843538f --- /dev/null +++ b/arch/arm/mach-rockchip/rk3399-board.c @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2017 Rockchip Electronics Co., Ltd + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include + +int board_late_init(void) +{ + setup_boot_mode(); + return 0; +} -- cgit v1.3.1 From b4d23f76430768c5eef0cc7f3d7fd2e0a420a3e0 Mon Sep 17 00:00:00 2001 From: Andy Yan Date: Wed, 11 Oct 2017 15:00:49 +0800 Subject: rockchip: add support for enter to bootrom download mode Rockchip bootrom will enter download mode if it returns from spl/tpl with a non-zero value and couldn't find a valid image in the backup partition. This patch provide a method to instruct the system to back to bootrom download mode by checking the BROM_DOWNLOAD_FLAG register. As the bootrom download function relys on some modules such as interrupts, so we need to back to bootrom as early as possbile before the tpl/spl code override the interrupt configurations. Signed-off-by: Andy Yan Reviewed-by: Kever Yang Acked-by: Philipp Tomsich Reviewed-by: Philipp Tomsich --- arch/arm/include/asm/arch-rockchip/boot_mode.h | 4 +++ arch/arm/mach-rockchip/Kconfig | 1 + arch/arm/mach-rockchip/bootrom.c | 47 ++++++++++++++++++++++++-- 3 files changed, 50 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/include/asm/arch-rockchip/boot_mode.h b/arch/arm/include/asm/arch-rockchip/boot_mode.h index 163b2e7b04d..6b2a610cf4c 100644 --- a/arch/arm/include/asm/arch-rockchip/boot_mode.h +++ b/arch/arm/include/asm/arch-rockchip/boot_mode.h @@ -15,7 +15,11 @@ #define BOOT_CHARGING (REBOOT_FLAG + 11) /* enter usb mass storage mode */ #define BOOT_UMS (REBOOT_FLAG + 12) +/* enter bootrom download mode */ +#define BOOT_BROM_DOWNLOAD 0xEF08A53C +#ifndef __ASSEMBLY__ int setup_boot_mode(void); +#endif #endif diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig index 6144057ad45..a26736a5aca 100644 --- a/arch/arm/mach-rockchip/Kconfig +++ b/arch/arm/mach-rockchip/Kconfig @@ -118,6 +118,7 @@ config ROCKCHIP_RK3399 select SPL_DRIVERS_MISC_SUPPORT select DEBUG_UART_BOARD_INIT select BOARD_LATE_INIT + select ROCKCHIP_BROM_HELPER help The Rockchip RK3399 is a ARM-based SoC with a dual-core Cortex-A72 and quad-core Cortex-A53. diff --git a/arch/arm/mach-rockchip/bootrom.c b/arch/arm/mach-rockchip/bootrom.c index e369fdc25a8..bef2a90d1fc 100644 --- a/arch/arm/mach-rockchip/bootrom.c +++ b/arch/arm/mach-rockchip/bootrom.c @@ -6,6 +6,8 @@ #include #include +#include +#include #include #include @@ -15,12 +17,45 @@ */ static jmp_buf brom_ctx __section(".data"); +static void _back_to_bootrom(enum rockchip_bootrom_cmd brom_cmd) +{ + longjmp(brom_ctx, brom_cmd); +} + void back_to_bootrom(enum rockchip_bootrom_cmd brom_cmd) { #if CONFIG_IS_ENABLED(LIBCOMMON_SUPPORT) puts("Returning to boot ROM...\n"); #endif - longjmp(brom_ctx, brom_cmd); + _back_to_bootrom(brom_cmd); +} + +/* + * we back to bootrom download mode if get a + * BOOT_BROM_DOWNLOAD flag in boot mode register + * + * note: the boot mode register is configured by + * application(next stage bootloader, kernel, etc), + * and the bootrom never check this register, so we need + * to check it and back to bootrom at very early bootstage(before + * some basic configurations(such as interrupts) been + * changed by TPL/SPL, as the bootrom download operation + * relys on many default settings(such as interrupts) by + * it's self. + */ +static bool check_back_to_brom_dnl_flag(void) +{ + u32 boot_mode; + + if (CONFIG_ROCKCHIP_BOOT_MODE_REG) { + boot_mode = readl(CONFIG_ROCKCHIP_BOOT_MODE_REG); + if (boot_mode == BOOT_BROM_DOWNLOAD) { + writel(0, CONFIG_ROCKCHIP_BOOT_MODE_REG); + return true; + } + } + + return false; } /* @@ -34,6 +69,8 @@ int save_boot_params(void) switch (ret) { case 0: + if (check_back_to_brom_dnl_flag()) + _back_to_bootrom(BROM_BOOT_ENTER_DNL); /* * This is the initial pass through this function * (i.e. saving the context), setjmp just setup up the @@ -54,7 +91,13 @@ int save_boot_params(void) */ ret = 0; break; - + case BROM_BOOT_ENTER_DNL: + /* + * A non-zero return value will instruct the BROM enter + * download mode. + */ + ret = 1; + break; default: #if CONFIG_IS_ENABLED(LIBCOMMON_SUPPORT) puts("FATAL: unexpected command to back_to_bootrom()\n"); -- cgit v1.3.1 From ecb103bf686f78df7fa65aa21346a8b36bd2bc5e Mon Sep 17 00:00:00 2001 From: Andy Yan Date: Wed, 11 Oct 2017 15:01:31 +0800 Subject: rockchip: check download key before bootup Enter download mode if the download key pressed. Signed-off-by: Andy Yan Acked-by: Philipp Tomsich Reviewed-by: Philipp Tomsich [Converted printfs in boot_mode.c to debug/pr_err:] Signed-off-by: Philipp Tomsich --- arch/arm/mach-rockchip/boot_mode.c | 49 +++++++++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-rockchip/boot_mode.c b/arch/arm/mach-rockchip/boot_mode.c index 46524900def..942849f2f84 100644 --- a/arch/arm/mach-rockchip/boot_mode.c +++ b/arch/arm/mach-rockchip/boot_mode.c @@ -5,26 +5,69 @@ */ #include +#include #include #include +void set_back_to_bootrom_dnl_flag(void) +{ + writel(BOOT_BROM_DOWNLOAD, CONFIG_ROCKCHIP_BOOT_MODE_REG); +} + +/* + * detect download key status by adc, most rockchip + * based boards use adc sample the download key status, + * but there are also some use gpio. So it's better to + * make this a weak function that can be override by + * some special boards. + */ +#define KEY_DOWN_MIN_VAL 0 +#define KEY_DOWN_MAX_VAL 30 + +__weak int rockchip_dnl_key_pressed(void) +{ + unsigned int val; + + if (adc_channel_single_shot("saradc", 1, &val)) { + pr_err("%s: adc_channel_single_shot fail!\n", __func__); + return false; + } + + if ((val >= KEY_DOWN_MIN_VAL) && (val <= KEY_DOWN_MAX_VAL)) + return true; + else + return false; +} + +void rockchip_dnl_mode_check(void) +{ + if (rockchip_dnl_key_pressed()) { + printf("download key pressed, entering download mode..."); + set_back_to_bootrom_dnl_flag(); + do_reset(NULL, 0, 0, NULL); + } +} + int setup_boot_mode(void) { void *reg = (void *)CONFIG_ROCKCHIP_BOOT_MODE_REG; int boot_mode = readl(reg); - debug("boot mode %x.\n", boot_mode); + rockchip_dnl_mode_check(); + + boot_mode = readl(reg); + debug("%s: boot mode 0x%08x\n", __func__, boot_mode); /* Clear boot mode */ writel(BOOT_NORMAL, reg); switch (boot_mode) { case BOOT_FASTBOOT: - printf("enter fastboot!\n"); + debug("%s: enter fastboot!\n", __func__); env_set("preboot", "setenv preboot; fastboot usb0"); break; case BOOT_UMS: - printf("enter UMS!\n"); + debug("%s: enter UMS!\n", __func__); env_set("preboot", "setenv preboot; ums mmc 0"); break; } -- cgit v1.3.1