From: Michael Srba <[email protected]> Prepare for supporting alternative boot0.h per-SoC by splitting out the existing msm8916-specific code.
There is now a selection mechanism to choose a specific boot0.h in the Kconfig. BOOT0_MSM8916_PSCI_WORKAROUND is the only option right now, but more can be added. The toplevel boot0.h additionally enables conditionally performing the include only in u-boot proper, or only in SPL. Signed-off-by: Michael Srba <[email protected]> --- arch/arm/mach-snapdragon/Kconfig | 16 ++++++ arch/arm/mach-snapdragon/include/mach/boot0.h | 58 +++------------------- .../mach-snapdragon/include/mach/msm8916_boot0.h | 54 ++++++++++++++++++++ configs/dragonboard410c_defconfig | 1 + 4 files changed, 77 insertions(+), 52 deletions(-) diff --git a/arch/arm/mach-snapdragon/Kconfig b/arch/arm/mach-snapdragon/Kconfig index d3de8693b5a..f863daf6bb9 100644 --- a/arch/arm/mach-snapdragon/Kconfig +++ b/arch/arm/mach-snapdragon/Kconfig @@ -42,4 +42,20 @@ config SYS_CONFIG_NAME Based on this option include/configs/<CONFIG_SYS_CONFIG_NAME>.h header will be used for board configuration. +choice + prompt "Qualcomm boot0.h workaround" + optional + help + While U-Boot on Qualcomm platforms doesn't generally need compile-time + adjustments based on the target SoC, workarounds in boot0.h can't + practically detect the SoC at runtime. Enable one of these workarounds + if you know you need it. + +config BOOT0_MSM8916_PSCI_WORKAROUND + bool "boot0.h workaround for buggy PSCI on the msm8916 SoC" + help + Select this if you are building U-Boot proper for an msm8916 board that + uses the buggy PSCI implementation. +endchoice + endif diff --git a/arch/arm/mach-snapdragon/include/mach/boot0.h b/arch/arm/mach-snapdragon/include/mach/boot0.h index 953cccad790..fb67aed7bc8 100644 --- a/arch/arm/mach-snapdragon/include/mach/boot0.h +++ b/arch/arm/mach-snapdragon/include/mach/boot0.h @@ -1,54 +1,8 @@ /* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Workaround for "PSCI bug" on DragonBoard 410c - * Copyright (C) 2021 Stephan Gerhold <[email protected]> - * - * 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? */ +#if defined(CONFIG_SPL_BUILD) 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: +#else +#if defined(CONFIG_BOOT0_MSM8916_PSCI_WORKAROUND) +#include "msm8916_boot0.h" +#endif +#endif diff --git a/arch/arm/mach-snapdragon/include/mach/msm8916_boot0.h b/arch/arm/mach-snapdragon/include/mach/msm8916_boot0.h new file mode 100644 index 00000000000..953cccad790 --- /dev/null +++ b/arch/arm/mach-snapdragon/include/mach/msm8916_boot0.h @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Workaround for "PSCI bug" on DragonBoard 410c + * Copyright (C) 2021 Stephan Gerhold <[email protected]> + * + * 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: diff --git a/configs/dragonboard410c_defconfig b/configs/dragonboard410c_defconfig index 51ad265688c..645f0816701 100644 --- a/configs/dragonboard410c_defconfig +++ b/configs/dragonboard410c_defconfig @@ -11,6 +11,7 @@ CONFIG_ENV_OFFSET=0x0 CONFIG_DEFAULT_DEVICE_TREE="qcom/apq8016-sbc" CONFIG_OF_LIBFDT_OVERLAY=y CONFIG_SYS_LOAD_ADDR=0x80080000 +CONFIG_BOOT0_MSM8916_PSCI_WORKAROUND=y CONFIG_IDENT_STRING="\nQualcomm-DragonBoard 410C" CONFIG_REMAKE_ELF=y CONFIG_BUTTON_CMD=y -- 2.53.0

