summaryrefslogtreecommitdiff
path: root/arch/arm/mach-snapdragon
diff options
context:
space:
mode:
authorStephan Gerhold <stephan@gerhold.net>2021-07-07 11:06:02 +0200
committerTom Rini <trini@konsulko.com>2021-07-23 18:53:45 -0400
commit0204d1b56b2fa681d9f47c2fed0c626d48429151 (patch)
tree230cc92043325e450f5c59704763b8857de41cc9 /arch/arm/mach-snapdragon
parent10189cb700114b81413934e63fac9c3e6b336887 (diff)
board: dragonboard410c: Load U-Boot directly without LK
At the moment the U-Boot port for the DragonBoard 410c is designed to be loaded as an Android boot image after Qualcomm's Little Kernel (LK) bootloader. This is simple to set up but LK is redundant in this case, since everything done by LK can be also done directly by U-Boot. Dropping LK entirely has at least the following advantages: - Easier installation/board code (no need for Android boot images) - (Slightly) faster boot - Boot directly in 64-bit without a round trip to 32-bit for LK So far this was not possible yet because of unsolved problems: 1. Signing tool: The firmware expects a "signed" ELF image with extra (Qualcomm-specific) ELF headers, usually used for secure boot. The DragonBoard 410c does not have secure boot by default but the extra ELF headers are still required. 2. PSCI bug: There seems to be a bug in the PSCI implementation (part of the TrustZone/tz firmware) that causes all other CPU cores to be started in 32-bit mode if LK is missing in the boot chain. This causes Linux to hang early during boot. There is a solution for both problems now: 1. qtestsign (https://github.com/msm8916-mainline/qtestsign) can be used as a "signing" tool for U-Boot and other firmware. 2. A workaround for the "PSCI bug" is to execute the TZ syscall when entering U-Boot. That way PSCI is made aware of the 64-bit switch and starts all other CPU cores in 64-bit mode as well. Simplify the dragonboard410c board by removing all the extra code that is only used to build an Android boot image that can be loaded by LK. This allows dropping the custom linker script, special image magic, as well as most of the special build/installation instructions. CONFIG_REMAKE_ELF is used to build a new ELF image that has both U-Boot and the appended DTB combined. The resulting u-boot.elf can then be passed to the "signing" tool (e.g. qtestsign). The PSCI workaround is placed in the "boot0" hook that is enabled with CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK. The extra check for EL1 allows compatibility with custom firmware that enters U-Boot in EL2 or EL3, e.g. qhypstub (https://github.com/msm8916-mainline/qhypstub). As a first step these changes apply only to DragonBoard410c. Similar changes could likely also work for the DragonBoard 820c. Note that removing LK wouldn't be possible that easily without a lot of work already done three years ago by Ramon Fried. A lot of missing initialization, pinctrl etc was already added back then even though it was not strictly needed yet. Cc: Ramon Fried <rfried.dev@gmail.com> Signed-off-by: Stephan Gerhold <stephan@gerhold.net>
Diffstat (limited to 'arch/arm/mach-snapdragon')
-rw-r--r--arch/arm/mach-snapdragon/Kconfig1
-rw-r--r--arch/arm/mach-snapdragon/include/mach/boot0.h54
2 files changed, 55 insertions, 0 deletions
diff --git a/arch/arm/mach-snapdragon/Kconfig b/arch/arm/mach-snapdragon/Kconfig
index e562d693c6..0ec74fa5d3 100644
--- a/arch/arm/mach-snapdragon/Kconfig
+++ b/arch/arm/mach-snapdragon/Kconfig
@@ -15,6 +15,7 @@ choice
config TARGET_DRAGONBOARD410C
bool "96Boards Dragonboard 410C"
select BOARD_LATE_INIT
+ select ENABLE_ARM_SOC_BOOT0_HOOK
help
Support for 96Boards Dragonboard 410C. This board complies with
96Board Open Platform Specifications. Features:
diff --git a/arch/arm/mach-snapdragon/include/mach/boot0.h b/arch/arm/mach-snapdragon/include/mach/boot0.h
new file mode 100644
index 0000000000..953cccad79
--- /dev/null
+++ b/arch/arm/mach-snapdragon/include/mach/boot0.h
@@ -0,0 +1,54 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Workaround for "PSCI bug" on DragonBoard 410c
+ * Copyright (C) 2021 Stephan Gerhold <stephan@gerhold.net>
+ *
+ * Syscall parameters taken from Qualcomm's LK fork (scm.h):
+ * Copyright (c) 2011-2015, The Linux Foundation. All rights reserved.
+ *
+ * The PSCI implementation in the TrustZone/tz firmware on DragonBoard 410c has
+ * a bug that starts all other CPU cores in 32-bit mode unless the TZ syscall
+ * that switches from 32-bit to 64-bit mode is executed at least once.
+ *
+ * Normally this happens inside Qualcomm's LK bootloader which runs in 32-bit
+ * mode and uses the TZ syscall to boot a kernel in 64-bit mode. However, if
+ * U-Boot is installed to the "aboot" partition (replacing LK) the switch to
+ * 64-bit mode never happens since U-Boot is already running in 64-bit mode.
+ *
+ * A workaround for this "PSCI bug" is to execute the TZ syscall when entering
+ * U-Boot. That way PSCI is made aware of the 64-bit switch and starts all other
+ * CPU cores in 64-bit mode as well.
+ */
+#include <linux/arm-smccc.h>
+
+#define ARM_SMCCC_SIP32_FAST_CALL \
+ ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_32, ARM_SMCCC_OWNER_SIP, 0)
+
+ /*
+ * U-Boot might be started in EL2 or EL3 with custom firmware.
+ * In that case, we assume that the workaround is not necessary or is
+ * handled already by the alternative firmware. Using the syscall in EL2
+ * would demote U-Boot to EL1; in EL3 it would probably just crash.
+ */
+ mrs x0, CurrentEL
+ cmp x0, #(1 << 2) /* EL1 */
+ bne reset
+
+ /* Prepare TZ syscall parameters */
+ mov x0, #ARM_SMCCC_SIP32_FAST_CALL
+ movk x0, #0x10f /* SCM_SVC_MILESTONE_CMD_ID */
+ mov x1, #0x12 /* MAKE_SCM_ARGS(0x2, SMC_PARAM_TYPE_BUFFER_READ) */
+ adr x2, el1_system_param
+ mov x3, el1_system_param_end - el1_system_param
+
+ /* Switch PSCI to 64-bit mode. Resets CPU and returns at el1_elr */
+ smc #0
+
+ /* Something went wrong, perhaps PSCI is already in 64-bit mode? */
+ b reset
+
+ .align 3
+el1_system_param:
+ .quad 0, 0, 0, 0, 0, 0, 0, 0, 0 /* el1_x0-x8 */
+ .quad reset /* el1_elr */
+el1_system_param_end: