diff options
-rw-r--r-- | src/arch/arm64/Makefile.mk | 13 | ||||
-rw-r--r-- | src/arch/arm64/include/armv8/arch/smc.h | 52 | ||||
-rw-r--r-- | src/arch/arm64/smc.c | 66 | ||||
-rw-r--r-- | src/arch/arm64/smc_asm.S | 9 |
4 files changed, 140 insertions, 0 deletions
diff --git a/src/arch/arm64/Makefile.mk b/src/arch/arm64/Makefile.mk index 897dae525f..6499283c08 100644 --- a/src/arch/arm64/Makefile.mk +++ b/src/arch/arm64/Makefile.mk @@ -30,6 +30,9 @@ bootblock-y += eabi_compat.c decompressor-$(CONFIG_ARM64_USE_ARCH_TIMER) += arch_timer.c bootblock-$(CONFIG_ARM64_USE_ARCH_TIMER) += arch_timer.c bootblock-y += transition.c transition_asm.S +ifneq ($(CONFIG_ARM64_CURRENT_EL),3) +bootblock-y += smc.c smc_asm.S +endif decompressor-y += memset.S bootblock-y += memset.S @@ -69,6 +72,9 @@ verstage-y += memcpy.S verstage-y += memmove.S verstage-y += transition.c transition_asm.S +ifneq ($(CONFIG_ARM64_CURRENT_EL),3) +verstage-y += smc.c smc_asm.S +endif endif # CONFIG_ARCH_VERSTAGE_ARM64 @@ -88,6 +94,9 @@ romstage-y += memmove.S romstage-y += ramdetect.c romstage-y += romstage.c romstage-y += transition.c transition_asm.S +ifneq ($(CONFIG_ARM64_CURRENT_EL),3) +romstage-y += smc.c smc_asm.S +endif rmodules_arm64-y += memset.S rmodules_arm64-y += memcpy.S @@ -109,6 +118,7 @@ ifeq ($(CONFIG_ARCH_RAMSTAGE_ARM64),y) ramstage-y += div0.c ramstage-y += eabi_compat.c ramstage-y += boot.c +ramstage-$(CONFIG_GENERATE_SMBIOS_TABLES) += smbios.c ramstage-y += tables.c ramstage-y += ramdetect.c ramstage-$(CONFIG_ARM64_USE_ARCH_TIMER) += arch_timer.c @@ -117,6 +127,9 @@ ramstage-y += memcpy.S ramstage-y += memmove.S ramstage-$(CONFIG_ARM64_USE_ARM_TRUSTED_FIRMWARE) += bl31.c ramstage-y += transition.c transition_asm.S +ifneq ($(CONFIG_ARM64_CURRENT_EL),3) +ramstage-y += smc.c smc_asm.S +endif ramstage-$(CONFIG_PAYLOAD_FIT_SUPPORT) += fit_payload.c ramstage-$(CONFIG_HAVE_ACPI_TABLES) += acpi.c ramstage-y += dma.c diff --git a/src/arch/arm64/include/armv8/arch/smc.h b/src/arch/arm64/include/armv8/arch/smc.h new file mode 100644 index 0000000000..2e7cc8a3c2 --- /dev/null +++ b/src/arch/arm64/include/armv8/arch/smc.h @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef ARM_ARM64_SMC_H +#define ARM_ARM64_SMC_H + +#include <types.h> + +uint64_t smc(uint32_t function_id, uint64_t arg1, uint64_t arg2, uint64_t arg3, + uint64_t arg4, uint64_t arg5, uint64_t arg6, uint64_t arg7); + +#define smc_call0(function_id) smc(function_id, 0, 0, 0, 0, 0, 0, 0) +#define smc_call1(function_id, a1) smc(function_id, a1, 0, 0, 0, 0, 0, 0) +#define smc_call2(function_id, a1, a2) smc(function_id, a1, a2, 0, 0, 0, 0, 0) +#define smc_call3(function_id, a1, a2, a3) smc(function_id, a1, a2, a3, 0, 0, 0, 0) + +/* Documented in https://developer.arm.com/documentation/den0022/ */ +enum psci_return_values { + PSCI_SUCCESS = 0, + PSCI_NOT_SUPPORTED = -1, + PSCI_INVALID_PARAMETERS = -2, + PSCI_DENIED = -3, + PSCI_ALREADY_ON = -4, + PSCI_ON_PENDING = -5, + PSCI_INTERNAL_FAILURE = -6, + PSCI_NOT_PRESENT = -7, + PSCI_DISABLED = -8, + PSCI_INVALID_ADDRESS = -9, +}; + +/* PSCI functions */ +#define PSCI_VERSION 0x84000000 +#define PSCI_FEATURES 0x8400000a + +/* Documented in https://developer.arm.com/documentation/den0028/ */ +enum smccc_return_values { + SMC_SUCCESS = 0, + SMC_NOT_SUPPORTED = -1, + SMC_NOT_REQUIRED = -2, + SMC_INVALID_PARAMETER = -3, +}; + +/* SMCCC functions */ +#define SMCCC_VERSION 0x80000000 +#define SMCCC_ARCH_FEATURES 0x80000001 +#define SMCCC_ARCH_SOC_ID 0x80000002 +#define SMCCC_GET_SOC_VERSION 0 +#define SMCCC_GET_SOC_REVISION 1 + +uint8_t smccc_supports_arch_soc_id(void); +enum cb_err smccc_arch_soc_id(uint32_t *jep106code, uint32_t *soc_revision); + +#endif /* ARM_ARM64_SMC_H */ diff --git a/src/arch/arm64/smc.c b/src/arch/arm64/smc.c new file mode 100644 index 0000000000..9a8883fcff --- /dev/null +++ b/src/arch/arm64/smc.c @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <arch/smc.h> +#include <console/console.h> +#include <types.h> + +/* Assumes at least a PSCI implementation is present */ +uint8_t smccc_supports_arch_soc_id(void) +{ + static uint8_t supported = 0xff; + uint64_t smc_ret; + + if (supported != 0xff) + return supported; + + // PSCI_FEATURES mandatory from PSCI 1.0 + smc_ret = smc_call0(PSCI_VERSION); + if (smc_ret < 0x10000) + goto fail; + + smc_ret = smc_call1(PSCI_FEATURES, SMCCC_VERSION); + if (smc_ret == PSCI_NOT_SUPPORTED) + goto fail; + + // SMCCC_ARCH_FEATURES supported from SMCCC 1.1 + smc_ret = smc_call0(SMCCC_VERSION); + if (smc_ret < 0x10001) + goto fail; + + smc_ret = smc_call1(SMCCC_ARCH_FEATURES, SMCCC_ARCH_SOC_ID); + if (smc_ret != SMC_SUCCESS) + goto fail; + + supported = 1; + return supported; + +fail: + supported = 0; + return supported; +} + +enum cb_err smccc_arch_soc_id(uint32_t *jep106code, uint32_t *soc_revision) +{ + uint64_t smc_ret; + + if (jep106code == NULL || soc_revision == NULL) + return CB_ERR_ARG; + + smc_ret = smc_call1(SMCCC_ARCH_SOC_ID, SMCCC_GET_SOC_VERSION); + if (smc_ret != SMC_INVALID_PARAMETER) + *jep106code = smc_ret; + else + *jep106code = -1; + + smc_ret = smc_call1(SMCCC_ARCH_SOC_ID, SMCCC_GET_SOC_REVISION); + if (smc_ret != SMC_INVALID_PARAMETER) + *soc_revision = smc_ret; + else + *soc_revision = -1; + + if (*jep106code == -1 || *soc_revision == -1) { + printk(BIOS_ERR, "SMCCC_ARCH_SOC_ID failed!\n"); + return CB_ERR; + } else + return CB_SUCCESS; +} diff --git a/src/arch/arm64/smc_asm.S b/src/arch/arm64/smc_asm.S new file mode 100644 index 0000000000..74b62c1ffa --- /dev/null +++ b/src/arch/arm64/smc_asm.S @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <arch/asm.h> + +ENTRY(smc) + /* W0, X1-X7 passed as arguments. Function ID is always W0. */ + smc #0 + ret /* X0 passed back as return value */ +ENDPROC(smc) |