diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/cpu/armv8/start.S | 13 | ||||
-rw-r--r-- | arch/arm/dts/synquacer-sc2a11-developerbox-u-boot.dtsi | 49 | ||||
-rw-r--r-- | arch/arm/include/asm/macro.h | 18 | ||||
-rw-r--r-- | arch/arm/include/asm/system.h | 6 | ||||
-rw-r--r-- | arch/arm/mach-snapdragon/Kconfig | 1 | ||||
-rw-r--r-- | arch/arm/mach-snapdragon/include/mach/boot0.h | 54 |
6 files changed, 136 insertions, 5 deletions
diff --git a/arch/arm/cpu/armv8/start.S b/arch/arm/cpu/armv8/start.S index 9e9c6140cd..b3eef705a5 100644 --- a/arch/arm/cpu/armv8/start.S +++ b/arch/arm/cpu/armv8/start.S @@ -127,10 +127,6 @@ pie_fixup_done: orr x0, x0, #0xf /* SCR_EL3.NS|IRQ|FIQ|EA */ msr scr_el3, x0 msr cptr_el3, xzr /* Enable FP/SIMD */ -#ifdef COUNTER_FREQUENCY - ldr x0, =COUNTER_FREQUENCY - msr cntfrq_el0, x0 /* Initialize CNTFRQ */ -#endif b 0f 2: mrs x1, hcr_el2 tbnz x1, #34, 1f /* HCR_EL2.E2H */ @@ -142,7 +138,14 @@ pie_fixup_done: mov x0, #3 << 20 msr cpacr_el1, x0 /* Enable FP/SIMD */ 0: - isb + +#ifdef COUNTER_FREQUENCY + branch_if_not_highest_el x0, 4f + ldr x0, =COUNTER_FREQUENCY + msr cntfrq_el0, x0 /* Initialize CNTFRQ */ +#endif + +4: isb /* * Enable SMPEN bit for coherency. diff --git a/arch/arm/dts/synquacer-sc2a11-developerbox-u-boot.dtsi b/arch/arm/dts/synquacer-sc2a11-developerbox-u-boot.dtsi index 2f13a42235..7a56116d6f 100644 --- a/arch/arm/dts/synquacer-sc2a11-developerbox-u-boot.dtsi +++ b/arch/arm/dts/synquacer-sc2a11-developerbox-u-boot.dtsi @@ -31,6 +31,55 @@ spi-max-frequency = <31250000>; spi-rx-bus-width = <0x1>; spi-tx-bus-width = <0x1>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "BootStrap-BL1"; + reg = <0x0 0x70000>; + read-only; + }; + + partition@70000 { + label = "Flash-Writer"; + reg = <0x70000 0x90000>; + read-only; + }; + + partition@100000 { + label = "SCP-BL2"; + reg = <0x100000 0x80000>; + read-only; + }; + + partition@180000 { + label = "FIP-TFA"; + reg = <0x180000 0x78000>; + }; + + partition@1f8000 { + label = "Stage2Tables"; + reg = <0x1f8000 0x8000>; + }; + + partition@200000 { + label = "U-Boot"; + reg = <0x200000 0x100000>; + }; + + partition@300000 { + label = "UBoot-Env"; + reg = <0x300000 0x100000>; + }; + + partition@500000 { + label = "Ex-OPTEE"; + reg = <0x500000 0x200000>; + }; + }; }; }; diff --git a/arch/arm/include/asm/macro.h b/arch/arm/include/asm/macro.h index bb33b4bc89..485310d660 100644 --- a/arch/arm/include/asm/macro.h +++ b/arch/arm/include/asm/macro.h @@ -78,6 +78,24 @@ lr .req x30 .endm /* + * Branch if we are not in the highest exception level + */ +.macro branch_if_not_highest_el, xreg, label + switch_el \xreg, 3f, 2f, 1f + +2: mrs \xreg, ID_AA64PFR0_EL1 + and \xreg, \xreg, #(ID_AA64PFR0_EL1_EL3) + cbnz \xreg, \label + b 3f + +1: mrs \xreg, ID_AA64PFR0_EL1 + and \xreg, \xreg, #(ID_AA64PFR0_EL1_EL3 | ID_AA64PFR0_EL1_EL2) + cbnz \xreg, \label + +3: +.endm + +/* * Branch if current processor is a Cortex-A57 core. */ .macro branch_if_a57_core, xreg, a57_label diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 11fceec4d2..8b3a54e64c 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h @@ -80,6 +80,12 @@ #define HCR_EL2_HCD_DIS (1 << 29) /* Hypervisor Call disabled */ /* + * ID_AA64PFR0_EL1 bits definitions + */ +#define ID_AA64PFR0_EL1_EL3 (0xF << 12) /* EL3 implemented */ +#define ID_AA64PFR0_EL1_EL2 (0xF << 8) /* EL2 implemented */ + +/* * CPACR_EL1 bits definitions */ #define CPACR_EL1_FPEN_EN (3 << 20) /* SIMD and FP instruction enabled */ 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: |