]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
firmware: arm_ffa: Register core as a platform driver
authorSudeep Holla <sudeep.holla@kernel.org>
Fri, 8 May 2026 17:54:16 +0000 (18:54 +0100)
committerSudeep Holla <sudeep.holla@kernel.org>
Sun, 17 May 2026 11:42:37 +0000 (12:42 +0100)
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 <yeoreum.yun@arm.com>
Link: https://patch.msgid.link/20260508-b4-ffa_plat_dev-v1-2-c5a30f8cf7b8@kernel.org
Signed-off-by: Sudeep Holla <sudeep.holla@kernel.org>
drivers/firmware/arm_ffa/common.h
drivers/firmware/arm_ffa/driver.c
drivers/firmware/arm_ffa/smccc.c

index 9c6425a81d0d5b7c56935ea4ed43f2c3904d37a1..5cdf4bd222c635250adee659a967046325c63e13 100644 (file)
@@ -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;
 }
index 8e1a070bbf83053e6fa8f990bee8d0b49926a89d..dd74f6c79749b2ea23b435658ba2873ab15dafc3 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/mm.h>
 #include <linux/mutex.h>
 #include <linux/of_irq.h>
+#include <linux/platform_device.h>
 #include <linux/scatterlist.h>
 #include <linux/slab.h>
 #include <linux/smp.h>
@@ -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);
 
index 4d85bfff0a4e6749990ad4db90c0225326c63857..e6125dd9f58f801bf2a9b69f11eccab61f9fac30 100644 (file)
@@ -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;