From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id B92B5C624DE for ; Fri, 4 Sep 2026 09:50:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=8welw8q80vDnCkJUseEYjZpwvSnOGyvDMguzpb/7+10=; b=WLV3HDf0No5biZtzPBpLj8NbwC zi0sSFrE+b82XsVMJzkTwRJY3D+gdOBvc/Y3bxsb0tIDrwLbR7A2IH4vY1mxP4IugB/sIchX8bGka Q1+YixkSpqRJbonNBHs0TwUQXM+gxC0MnLR10YooBSHWY9cSAjXq3hapw53DU22/Wa3Buef9G2a9r bMznvy27d1OoUcZ8ZuSEaiNoidllHoya+YnNS3lyF4NBU423BTrIh6Pcbx2vSBeZAZuc09ePFgCLX 2jS5zOeN75pjbXRka1bnqXtBuNDiAof5Jw/hVAsWPBjLuL0umCbzyQE6JBrbXm3y958QfBVznU7r2 DAHAP+mg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.99.1 #2 (Red Hat Linux)) id 1x2QYz-00000001ZuD-2Rgo; Fri, 04 Sep 2026 09:50:25 +0000 Received: from tor.source.kernel.org ([172.105.4.254]) by bombadil.infradead.org with esmtps (Exim 4.99.1 #2 (Red Hat Linux)) id 1x2QYy-00000001Ztk-0CTF for linux-arm-kernel@lists.infradead.org; Fri, 04 Sep 2026 09:50:24 +0000 Received: from smtp.kernel.org (quasi.space.kernel.org [100.103.45.18]) by tor.source.kernel.org (Postfix) with ESMTP id 3F08D60A83; Fri, 4 Sep 2026 09:50:23 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id AA66E1F00A3E; Fri, 4 Sep 2026 09:50:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1788515422; bh=8welw8q80vDnCkJUseEYjZpwvSnOGyvDMguzpb/7+10=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=akzgCTCBGKJPAZI09qhodXTWgASlEDdS3PyqAwUbcJ0HePXgzjlGMtvDCSCLIKqT/ YmgcjgutQnAV4awQjdQOoS0YLfZhec5R6KahWrkzYLussnekzlUvtqYWuya4RHzRQ0 1YxaqcCp6/+9XC/1C6zYjqIuQqJgav1WxNAFk6fN/K9F8Rv5axlcy7BOp5F5mAJQVF rI2sw/Ie02jS+8gU6M4nDAUXuuW+wQSRofrcTVkbyqqzIh+sowKKmODL/Kl/Y15c50 5UPqEvks8RVnXhFnG2bjsiNKowCtE599zQoyGi7/Ya7SDUAA7Aq/UNtrgs/qBDJKRn hOWllgs+e6hsQ== From: "Aneesh Kumar K.V (Arm)" To: linux-coco@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Cc: "Aneesh Kumar K.V (Arm)" , Catalin Marinas , Greg KH , Jeremy Linton , Jonathan Cameron , Lorenzo Pieralisi , Mark Rutland , Sudeep Holla , Will Deacon , Steven Price , Suzuki K Poulose , Andre Przywara Subject: [PATCH v10 1/7] firmware: smccc: Add an Arm SMCCC bus Date: Fri, 4 Sep 2026 15:19:54 +0530 Message-ID: <20260904095000.1184861-2-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260904095000.1184861-1-aneesh.kumar@kernel.org> References: <20260904095000.1184861-1-aneesh.kumar@kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org SMCCC-discovered firmware services are currently represented by separate platform devices, such as smccc_trng and arm-cca-dev. Those devices do not represent independent DT/ACPI-described platform resources; they are features of the SMCCC firmware interface. Add an Arm SMCCC bus for services discovered through the SMCCC firmware interface. The bus provides SMCCC device and driver registration helpers, name-based matching, modalias generation, and a sysfs modalias attribute so SMCCC service drivers can bind to discovered firmware services and autoload as modules. Follow-up changes can then register SMCCC firmware services as arm-smccc devices instead of creating independent per-feature platform devices. Based on arm_ffa code Signed-off-by: Aneesh Kumar K.V (Arm) --- drivers/firmware/smccc/Makefile | 2 +- drivers/firmware/smccc/bus.c | 151 ++++++++++++++++++++++++++++ include/linux/arm-smccc-bus.h | 48 +++++++++ include/linux/device-id/arm_smccc.h | 15 +++ include/linux/mod_devicetable.h | 1 + scripts/mod/devicetable-offsets.c | 3 + scripts/mod/file2alias.c | 8 ++ 7 files changed, 227 insertions(+), 1 deletion(-) create mode 100644 drivers/firmware/smccc/bus.c create mode 100644 include/linux/arm-smccc-bus.h create mode 100644 include/linux/device-id/arm_smccc.h diff --git a/drivers/firmware/smccc/Makefile b/drivers/firmware/smccc/Makefile index 40d19144a860..68bbff1407b8 100644 --- a/drivers/firmware/smccc/Makefile +++ b/drivers/firmware/smccc/Makefile @@ -1,4 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 # -obj-$(CONFIG_HAVE_ARM_SMCCC_DISCOVERY) += smccc.o kvm_guest.o +obj-$(CONFIG_HAVE_ARM_SMCCC_DISCOVERY) += bus.o smccc.o kvm_guest.o obj-$(CONFIG_ARM_SMCCC_SOC_ID) += soc_id.o diff --git a/drivers/firmware/smccc/bus.c b/drivers/firmware/smccc/bus.c new file mode 100644 index 000000000000..caba1a03c997 --- /dev/null +++ b/drivers/firmware/smccc/bus.c @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2026 Arm Limited + */ + +#include +#include + +static int arm_smccc_bus_match(struct device *dev, + const struct device_driver *drv) +{ + const struct arm_smccc_device_id *id_table; + struct arm_smccc_device *smccc_dev = to_arm_smccc_device(dev); + + id_table = to_arm_smccc_driver(drv)->id_table; + if (!id_table) + return 0; + + while (id_table->func_id) { + if (smccc_dev->func_id == id_table->func_id) + return 1; + id_table++; + } + + return 0; +} + +static int arm_smccc_bus_probe(struct device *dev) +{ + struct arm_smccc_driver *smccc_drv = to_arm_smccc_driver(dev->driver); + + return smccc_drv->probe(to_arm_smccc_device(dev)); +} + +static void arm_smccc_bus_remove(struct device *dev) +{ + struct arm_smccc_driver *smcc_drv = to_arm_smccc_driver(dev->driver); + + if (smcc_drv->remove) + smcc_drv->remove(to_arm_smccc_device(dev)); +} + +static int arm_smccc_bus_uevent(const struct device *dev, + struct kobj_uevent_env *env) +{ + const struct arm_smccc_device *smccc_dev = to_arm_smccc_device(dev); + + return add_uevent_var(env, "MODALIAS=" ARM_SMCCC_MODULE_PREFIX "f%08X", + smccc_dev->func_id); +} + +static ssize_t modalias_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct arm_smccc_device *smccc_dev = to_arm_smccc_device(dev); + + return sysfs_emit(buf, ARM_SMCCC_MODULE_PREFIX "f%08X\n", + smccc_dev->func_id); +} +static DEVICE_ATTR_RO(modalias); + +static struct attribute *arm_smccc_device_attrs[] = { + &dev_attr_modalias.attr, + NULL, +}; +ATTRIBUTE_GROUPS(arm_smccc_device); + +const struct bus_type arm_smccc_bus_type = { + .name = "arm_smccc", + .match = arm_smccc_bus_match, + .probe = arm_smccc_bus_probe, + .remove = arm_smccc_bus_remove, + .uevent = arm_smccc_bus_uevent, + .dev_groups = arm_smccc_device_groups, +}; +EXPORT_SYMBOL_GPL(arm_smccc_bus_type); + +int arm_smccc_driver_register(struct arm_smccc_driver *driver, + struct module *owner, const char *mod_name) +{ + if (!driver->probe || !driver->id_table) + return -EINVAL; + + driver->driver.bus = &arm_smccc_bus_type; + driver->driver.name = driver->name; + driver->driver.owner = owner; + driver->driver.mod_name = mod_name; + + return driver_register(&driver->driver); +} +EXPORT_SYMBOL_GPL(arm_smccc_driver_register); + +void arm_smccc_driver_unregister(struct arm_smccc_driver *driver) +{ + driver_unregister(&driver->driver); +} +EXPORT_SYMBOL_GPL(arm_smccc_driver_unregister); + +static void arm_smccc_release_device(struct device *dev) +{ + struct arm_smccc_device *smccc_dev = to_arm_smccc_device(dev); + + kfree(smccc_dev); +} + +struct arm_smccc_device *arm_smccc_device_register(const char *name, u32 func_id) +{ + int ret; + struct arm_smccc_device *smccc_dev; + + if (!name) + return ERR_PTR(-EINVAL); + + smccc_dev = kzalloc_obj(*smccc_dev); + if (!smccc_dev) + return ERR_PTR(-ENOMEM); + + smccc_dev->func_id = func_id; + smccc_dev->dev.bus = &arm_smccc_bus_type; + smccc_dev->dev.release = arm_smccc_release_device; + + ret = dev_set_name(&smccc_dev->dev, "%s", name); + if (ret) { + kfree(smccc_dev); + return ERR_PTR(ret); + } + + ret = device_register(&smccc_dev->dev); + if (ret) { + put_device(&smccc_dev->dev); + return ERR_PTR(ret); + } + + return smccc_dev; +} +EXPORT_SYMBOL_GPL(arm_smccc_device_register); + +void arm_smccc_device_unregister(struct arm_smccc_device *smccc_dev) +{ + if (!smccc_dev) + return; + + device_unregister(&smccc_dev->dev); +} +EXPORT_SYMBOL_GPL(arm_smccc_device_unregister); + +static int __init arm_smccc_bus_init(void) +{ + return bus_register(&arm_smccc_bus_type); +} +subsys_initcall(arm_smccc_bus_init); diff --git a/include/linux/arm-smccc-bus.h b/include/linux/arm-smccc-bus.h new file mode 100644 index 000000000000..cde268fc2930 --- /dev/null +++ b/include/linux/arm-smccc-bus.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2026 Arm Limited + */ +#ifndef __LINUX_ARM_SMCCC_BUS_H +#define __LINUX_ARM_SMCCC_BUS_H + +#include +#include +#include + +struct arm_smccc_device { + struct device dev; + u32 func_id; +}; + +#define to_arm_smccc_device(d) container_of(d, struct arm_smccc_device, dev) + +struct arm_smccc_driver { + struct device_driver driver; + + const char *name; + int (*probe)(struct arm_smccc_device *sdev); + void (*remove)(struct arm_smccc_device *sdev); + const struct arm_smccc_device_id *id_table; +}; + +#define to_arm_smccc_driver(d) \ + container_of_const(d, struct arm_smccc_driver, driver) + +int arm_smccc_driver_register(struct arm_smccc_driver *driver, + struct module *owner, const char *mod_name); +void arm_smccc_driver_unregister(struct arm_smccc_driver *driver); +struct arm_smccc_device *arm_smccc_device_register(const char *name, u32 func_id); +void arm_smccc_device_unregister(struct arm_smccc_device *smcc_dev); + +#define arm_smccc_register(driver) \ + arm_smccc_driver_register(driver, THIS_MODULE, KBUILD_MODNAME) +#define arm_smccc_unregister(driver) \ + arm_smccc_driver_unregister(driver) + +#define module_arm_smccc_driver(__arm_smccc_driver) \ + module_driver(__arm_smccc_driver, arm_smccc_register, \ + arm_smccc_unregister) + +extern const struct bus_type arm_smccc_bus_type; + +#endif /* __LINUX_ARM_SMCCC_BUS_H */ diff --git a/include/linux/device-id/arm_smccc.h b/include/linux/device-id/arm_smccc.h new file mode 100644 index 000000000000..537bbf7a7fd5 --- /dev/null +++ b/include/linux/device-id/arm_smccc.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __LINUX_DEVICE_ID_ARM_SMCCC_H +#define __LINUX_DEVICE_ID_ARM_SMCCC_H + +#define ARM_SMCCC_MODULE_PREFIX "arm_smccc:" + +/** + * struct arm_smccc_device_id - Arm SMCCC bus device identifier + * @func_id: SMCCC function identifier + */ +struct arm_smccc_device_id { + __u32 func_id; +}; + +#endif /* __LINUX_DEVICE_ID_ARM_SMCCC_H */ diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index a397213bedac..318c4b5c3451 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h @@ -16,6 +16,7 @@ #include "device-id/amba.h" #include "device-id/ap.h" #include "device-id/apr.h" +#include "device-id/arm_smccc.h" #include "device-id/auxiliary.h" #include "device-id/bcma.h" #include "device-id/ccw.h" diff --git a/scripts/mod/devicetable-offsets.c b/scripts/mod/devicetable-offsets.c index b4178c42d08f..1492e9fdc7cb 100644 --- a/scripts/mod/devicetable-offsets.c +++ b/scripts/mod/devicetable-offsets.c @@ -254,6 +254,9 @@ int main(void) DEVID(auxiliary_device_id); DEVID_FIELD(auxiliary_device_id, name); + DEVID(arm_smccc_device_id); + DEVID_FIELD(arm_smccc_device_id, func_id); + DEVID(ssam_device_id); DEVID_FIELD(ssam_device_id, match_flags); DEVID_FIELD(ssam_device_id, domain); diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 8d36c74dec2d..980d7da456bb 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -1349,6 +1349,13 @@ static void do_auxiliary_entry(struct module *mod, void *symval) module_alias_printf(mod, false, AUXILIARY_MODULE_PREFIX "%s", *name); } +static void do_arm_smccc_entry(struct module *mod, void *symval) +{ + DEF_FIELD(symval, arm_smccc_device_id, func_id); + + module_alias_printf(mod, false, ARM_SMCCC_MODULE_PREFIX "f%08X", func_id); +} + /* * Looks like: ssam:dNcNtNiNfN * @@ -1519,6 +1526,7 @@ static const struct devtable devtable[] = { {"mhi", SIZE_mhi_device_id, do_mhi_entry}, {"mhi_ep", SIZE_mhi_device_id, do_mhi_ep_entry}, {"auxiliary", SIZE_auxiliary_device_id, do_auxiliary_entry}, + {"arm_smccc", SIZE_arm_smccc_device_id, do_arm_smccc_entry}, {"ssam", SIZE_ssam_device_id, do_ssam_entry}, {"dfl", SIZE_dfl_device_id, do_dfl_entry}, {"ishtp", SIZE_ishtp_device_id, do_ishtp_entry}, -- 2.43.0