diff --git a/xen/arch/arm/firmware/Kconfig b/xen/arch/arm/firmware/Kconfig index fc7918c7fc..bbf88fbb9a 100644 --- a/xen/arch/arm/firmware/Kconfig +++ b/xen/arch/arm/firmware/Kconfig @@ -8,9 +8,18 @@ config ARM_SCI menu "Firmware Drivers" +choice + prompt "ARM SCI driver type" + default SCMI_SMC + help + Choose which ARM SCI driver to enable. + +config ARM_SCI_NONE + bool "none" + config SCMI_SMC bool "Forward SCMI over SMC calls from hwdom to EL3 firmware" - default y + select ARM_SCI help This option enables basic awareness for SCMI calls using SMC as doorbell mechanism and Shared Memory for transport ("arm,scmi-smc" @@ -18,4 +27,6 @@ config SCMI_SMC firmware node is used to trap and forward corresponding SCMI SMCs to firmware running at EL3, for calls coming from the hardware domain. +endchoice + endmenu diff --git a/xen/arch/arm/firmware/scmi-smc.c b/xen/arch/arm/firmware/scmi-smc.c index 33473c04b1..4c5df714c2 100644 --- a/xen/arch/arm/firmware/scmi-smc.c +++ b/xen/arch/arm/firmware/scmi-smc.c @@ -16,12 +16,12 @@ #include #include +#include +#include #include -#include #define SCMI_SMC_ID_PROP "arm,smc-id" -static bool __ro_after_init scmi_enabled; static uint32_t __ro_after_init scmi_smc_id; /* @@ -41,14 +41,11 @@ static bool scmi_is_valid_smc_id(uint32_t fid) * * Returns true if SMC was handled (regardless of response), false otherwise. */ -bool scmi_handle_smc(struct cpu_user_regs *regs) +static bool scmi_handle_smc(struct cpu_user_regs *regs) { uint32_t fid = (uint32_t)get_user_reg(regs, 0); struct arm_smccc_res res; - if ( !scmi_enabled ) - return false; - if ( !scmi_is_valid_smc_id(fid) ) return false; @@ -78,6 +75,25 @@ bool scmi_handle_smc(struct cpu_user_regs *regs) return true; } +static int scmi_smc_domain_init(struct domain *d, + struct xen_domctl_createdomain *config) +{ + if ( !is_hardware_domain(d) ) + return 0; + + d->arch.sci_enabled = true; + printk(XENLOG_DEBUG "SCMI: %pd init\n", d); + return 0; +} + +static void scmi_smc_domain_destroy(struct domain *d) +{ + if ( !is_hardware_domain(d) ) + return; + + printk(XENLOG_DEBUG "SCMI: %pd destroy\n", d); +} + static int __init scmi_check_smccc_ver(void) { if ( smccc_ver < ARM_SMCCC_VERSION_1_1 ) @@ -90,37 +106,14 @@ static int __init scmi_check_smccc_ver(void) return 0; } -static int __init scmi_dt_init_smccc(void) -{ - static const struct dt_device_match scmi_ids[] __initconst = - { - /* We only support "arm,scmi-smc" binding for now */ - DT_MATCH_COMPATIBLE("arm,scmi-smc"), - { /* sentinel */ }, - }; - const struct dt_device_node *scmi_node; - int ret; - - /* If no SCMI firmware node found, fail silently as it's not mandatory */ - scmi_node = dt_find_matching_node(NULL, scmi_ids); - if ( !scmi_node ) - return -EOPNOTSUPP; - - ret = dt_property_read_u32(scmi_node, SCMI_SMC_ID_PROP, &scmi_smc_id); - if ( !ret ) - { - printk(XENLOG_ERR "SCMI: No valid \"%s\" property in \"%s\" DT node\n", - SCMI_SMC_ID_PROP, scmi_node->full_name); - return -ENOENT; - } - - scmi_enabled = true; - - return 0; -} +static const struct sci_mediator_ops scmi_smc_ops = { + .handle_call = scmi_handle_smc, + .domain_init = scmi_smc_domain_init, + .domain_destroy = scmi_smc_domain_destroy, +}; /* Initialize the SCMI layer based on SMCs and Device-tree */ -static int __init scmi_init(void) +static int __init scmi_dom0_init(struct dt_device_node *dev, const void *data) { int ret; @@ -134,22 +127,36 @@ static int __init scmi_init(void) if ( ret ) return ret; - ret = scmi_dt_init_smccc(); - if ( ret == -EOPNOTSUPP ) - return ret; + ret = dt_property_read_u32(dev, SCMI_SMC_ID_PROP, &scmi_smc_id); + if ( !ret ) + { + printk(XENLOG_ERR "SCMI: No valid \"%s\" property in \"%s\" DT node\n", + SCMI_SMC_ID_PROP, dt_node_full_name(dev)); + return -ENOENT; + } + + ret = sci_register(&scmi_smc_ops); if ( ret ) - goto err; + { + printk(XENLOG_ERR "SCMI: mediator already registered (ret = %d)\n", + ret); + return ret; + } printk(XENLOG_INFO "Using SCMI with SMC ID: 0x%x\n", scmi_smc_id); return 0; - - err: - printk(XENLOG_ERR "SCMI: Initialization failed (ret = %d)\n", ret); - return ret; } -__initcall(scmi_init); +static const struct dt_device_match scmi_smc_match[] __initconst = { + DT_MATCH_COMPATIBLE("arm,scmi-smc"), + { /* sentinel */ }, +}; + +DT_DEVICE_START(scmi_smc, "SCMI SMC DOM0", DEVICE_FIRMWARE) + .dt_match = scmi_smc_match, + .init = scmi_dom0_init, +DT_DEVICE_END /* * Local variables: diff --git a/xen/arch/arm/include/asm/firmware/scmi-smc.h b/xen/arch/arm/include/asm/firmware/scmi-smc.h deleted file mode 100644 index 6b1a164a40..0000000000 --- a/xen/arch/arm/include/asm/firmware/scmi-smc.h +++ /dev/null @@ -1,41 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * xen/arch/arm/include/asm/firmware/scmi-smc.h - * - * ARM System Control and Management Interface (SCMI) over SMC - * Generic handling layer - * - * Andrei Cherechesu - * Copyright 2024 NXP - */ - -#ifndef __ASM_SCMI_SMC_H__ -#define __ASM_SCMI_SMC_H__ - -#include - -struct cpu_user_regs; - -#ifdef CONFIG_SCMI_SMC - -bool scmi_handle_smc(struct cpu_user_regs *regs); - -#else - -static inline bool scmi_handle_smc(struct cpu_user_regs *regs) -{ - return false; -} - -#endif /* CONFIG_SCMI_SMC */ - -#endif /* __ASM_SCMI_H__ */ - -/* - * Local variables: - * mode: C - * c-file-style: "BSD" - * c-basic-offset: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/xen/arch/arm/vsmc.c b/xen/arch/arm/vsmc.c index 4095171533..78d5bdf56f 100644 --- a/xen/arch/arm/vsmc.c +++ b/xen/arch/arm/vsmc.c @@ -21,7 +21,6 @@ #include #include #include -#include /* Number of functions currently supported by Hypervisor Service. */ #define XEN_SMCCC_FUNCTION_COUNT 3 @@ -233,7 +232,7 @@ static bool handle_sip(struct cpu_user_regs *regs) if ( platform_smc(regs) ) return true; - return (scmi_handle_smc(regs)) ? true : sci_handle_call(regs); + return sci_handle_call(regs); } /* diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h index e7a17ede3e..b31324f8d4 100644 --- a/xen/include/public/arch-arm.h +++ b/xen/include/public/arch-arm.h @@ -328,6 +328,7 @@ DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t); #define XEN_DOMCTL_CONFIG_TEE_FFA 2 #define XEN_DOMCTL_CONFIG_ARM_SCI_NONE 0 +#define XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC 1 struct xen_arch_domainconfig { /* IN/OUT */