From: Sudeep Holla Date: Fri, 8 May 2026 17:54:16 +0000 (+0100) Subject: firmware: arm_ffa: Register core as a platform driver X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e659fc8e537c7a21d5d693d6f30d8852f2fa8d91;p=thirdparty%2Fkernel%2Flinux.git firmware: arm_ffa: Register core as a platform driver Move the FF-A core bring-up and teardown paths into platform driver probe and remove callbacks, and register a synthetic arm-ffa platform device to bind the driver. This makes the FF-A core lifetime follow the driver model while keeping the device creation internal to the FF-A core. Use normal platform driver registration so the probe path has standard driver-core semantics. The synthetic platform device is a temporary bridge until ACPI and devicetree describe the FF-A core device or object. Once those firmware description paths are defined, the internal platform device creation can be dropped and the driver can bind to the firmware-described device directly. Since the transport selection now happens from the platform probe path, drop the __init annotation from ffa_transport_init(). Reviewed-by: Yeoreum Yun Link: https://patch.msgid.link/20260508-b4-ffa_plat_dev-v1-2-c5a30f8cf7b8@kernel.org Signed-off-by: Sudeep Holla --- diff --git a/drivers/firmware/arm_ffa/common.h b/drivers/firmware/arm_ffa/common.h index 9c6425a81d0d5..5cdf4bd222c63 100644 --- a/drivers/firmware/arm_ffa/common.h +++ b/drivers/firmware/arm_ffa/common.h @@ -18,9 +18,9 @@ bool ffa_device_is_valid(struct ffa_device *ffa_dev); void ffa_device_match_uuid(struct ffa_device *ffa_dev, const uuid_t *uuid); #ifdef CONFIG_ARM_FFA_SMCCC -int __init ffa_transport_init(ffa_fn **invoke_ffa_fn); +int ffa_transport_init(ffa_fn **invoke_ffa_fn); #else -static inline int __init ffa_transport_init(ffa_fn **invoke_ffa_fn) +static inline int ffa_transport_init(ffa_fn **invoke_ffa_fn) { return -EOPNOTSUPP; } diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c index 8e1a070bbf830..dd74f6c79749b 100644 --- a/drivers/firmware/arm_ffa/driver.c +++ b/drivers/firmware/arm_ffa/driver.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -46,6 +47,7 @@ #define FFA_DRIVER_VERSION FFA_VERSION_1_2 #define FFA_MIN_VERSION FFA_VERSION_1_0 +#define FFA_PLATFORM_NAME "arm-ffa" #define SENDER_ID_MASK GENMASK(31, 16) #define RECEIVER_ID_MASK GENMASK(15, 0) @@ -115,6 +117,7 @@ struct ffa_drv_info { }; static struct ffa_drv_info *drv_info; +static struct platform_device *ffa_pdev; /* * The driver must be able to support all the versions from the earliest @@ -2086,7 +2089,7 @@ cleanup: ffa_notifications_cleanup(); } -static int __init ffa_init(void) +static int ffa_probe(struct platform_device *pdev) { int ret; u32 buf_sz; @@ -2099,6 +2102,7 @@ static int __init ffa_init(void) drv_info = kzalloc_obj(*drv_info); if (!drv_info) return -ENOMEM; + platform_set_drvdata(pdev, drv_info); ret = ffa_version_check(&drv_info->version); if (ret) @@ -2161,19 +2165,56 @@ free_pages: free_pages_exact(drv_info->tx_buffer, rxtx_bufsz); free_pages_exact(drv_info->rx_buffer, rxtx_bufsz); free_drv_info: + platform_set_drvdata(pdev, NULL); kfree(drv_info); + drv_info = NULL; return ret; } -module_init(ffa_init); -static void __exit ffa_exit(void) +static void ffa_remove(struct platform_device *pdev) { + struct ffa_drv_info *info = platform_get_drvdata(pdev); + ffa_notifications_cleanup(); ffa_partitions_cleanup(); ffa_rxtx_unmap(); - free_pages_exact(drv_info->tx_buffer, drv_info->rxtx_bufsz); - free_pages_exact(drv_info->rx_buffer, drv_info->rxtx_bufsz); - kfree(drv_info); + free_pages_exact(info->tx_buffer, info->rxtx_bufsz); + free_pages_exact(info->rx_buffer, info->rxtx_bufsz); + kfree(info); + platform_set_drvdata(pdev, NULL); + drv_info = NULL; +} + +static struct platform_driver ffa_driver = { + .probe = ffa_probe, + .remove = ffa_remove, + .driver = { + .name = FFA_PLATFORM_NAME, + }, +}; + +static int __init ffa_init(void) +{ + int ret; + + ffa_pdev = platform_device_register_simple(FFA_PLATFORM_NAME, + PLATFORM_DEVID_NONE, + NULL, 0); + if (IS_ERR(ffa_pdev)) + return PTR_ERR(ffa_pdev); + + ret = platform_driver_register(&ffa_driver); + if (ret) + platform_device_unregister(ffa_pdev); + + return ret; +} +module_init(ffa_init); + +static void __exit ffa_exit(void) +{ + platform_device_unregister(ffa_pdev); + platform_driver_unregister(&ffa_driver); } module_exit(ffa_exit); diff --git a/drivers/firmware/arm_ffa/smccc.c b/drivers/firmware/arm_ffa/smccc.c index 4d85bfff0a4e6..e6125dd9f58f8 100644 --- a/drivers/firmware/arm_ffa/smccc.c +++ b/drivers/firmware/arm_ffa/smccc.c @@ -17,7 +17,7 @@ static void __arm_ffa_fn_hvc(ffa_value_t args, ffa_value_t *res) arm_smccc_1_2_hvc(&args, res); } -int __init ffa_transport_init(ffa_fn **invoke_ffa_fn) +int ffa_transport_init(ffa_fn **invoke_ffa_fn) { enum arm_smccc_conduit conduit;