From: Harshal Dev <harshal.dev@oss.qualcomm.com>
To: Eric Biggers <ebiggers@kernel.org>,
Bjorn Andersson <andersson@kernel.org>,
Konrad Dybcio <konradybcio@kernel.org>,
Abel Vesa <abelvesa@kernel.org>,
Kuldeep Singh <kuldeep.singh@oss.qualcomm.com>,
Neeraj Soni <neeraj.soni@oss.qualcomm.com>,
Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>,
Sumit Garg <sumit.garg@oss.qualcomm.com>,
Selvam Sathappan Periakaruppan
<selvam.periakaruppan@oss.qualcomm.com>
Cc: Basant Kumar <basantk@qti.qualcomm.com>,
linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org,
linux-crypto@vger.kernel.org,
Harshal Dev <harshal.dev@oss.qualcomm.com>
Subject: [PATCH v2 4/6] tee: optee: Register TEE devices on the platform bus
Date: Wed, 11 Nov 2026 19:47:04 +0530 [thread overview]
Message-ID: <20261111-ice-migrate-tee-svc-v2-4-29d19f6c92ab@oss.qualcomm.com> (raw)
In-Reply-To: <20261111-ice-migrate-tee-svc-v2-0-29d19f6c92ab@oss.qualcomm.com>
The Qualcomm Inline Crypto Engine (ICE) driver is an independent platform
driver which polls on availability of a TEE interface (SCM driver) before
checking if the ICE secure service is supported by QTEE by querying the
qcom_scm_ice_available() API.
The TEE subsystem currently does not provide any way to notify regarding
the availability of a TEE interface, i.e. whether QCOMTEE or OPTEE have
probed. And so when migrating to the TEE subsystem via an ICE TEE client
driver, ICE needs to defer probe until the OPTEE ICE Pseudo TA becomes
available on the TEE bus. This means that for OPTEE builds without the
ICE PTA, the ICE driver would indefintely defer probe and the dependent
UFS/SDHC storage driver will fail to come online.
Add support for optionally registering the back-end TEE devices which
represent a particular TEE (say OPTEE) on the platform bus via the
tee_platform_device_register() API. This allows drivers which poll on
TEE secure interface availability to be notified even if the TEE service
itself is not supported.
Signed-off-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
---
MAINTAINERS | 1 +
drivers/firmware/qcom/qcom_ice_tee.c | 41 ++++++++++++++++++++++++++++++
drivers/soc/qcom/Kconfig | 1 +
drivers/soc/qcom/ice.c | 9 ++++++-
drivers/tee/optee/ffa_abi.c | 8 ++++++
drivers/tee/optee/smc_abi.c | 8 ++++++
drivers/tee/tee_core.c | 21 +++++++++++++++
include/linux/firmware/qcom/qcom_ice_tee.h | 10 ++++++++
include/linux/tee_core.h | 9 +++++++
9 files changed, 107 insertions(+), 1 deletion(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index 1132e456488b..06dba76996b8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -23013,6 +23013,7 @@ L: linux-arm-msm@vger.kernel.org
L: linux-crypto@vger.kernel.org
S: Maintained
F: drivers/firmware/qcom/qcom_ice_tee.c
+F: include/linux/firmware/qcom/qcom_ice_tee.h
QUALCOMM INTERCONNECT BWMON DRIVER
M: Krzysztof Kozlowski <krzk@kernel.org>
diff --git a/drivers/firmware/qcom/qcom_ice_tee.c b/drivers/firmware/qcom/qcom_ice_tee.c
index 694aa05847f0..39f7094439d9 100644
--- a/drivers/firmware/qcom/qcom_ice_tee.c
+++ b/drivers/firmware/qcom/qcom_ice_tee.c
@@ -5,6 +5,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/tee_drv.h>
#include <linux/uuid.h>
@@ -22,6 +23,9 @@
#define TEE_NUM_PARAMS 4
+/* This represents the back-end OPTEE device */
+static struct device *__teedev;
+
struct qcom_ice_tee_private {
struct device *dev;
struct tee_context *ctx;
@@ -281,6 +285,18 @@ static int qcom_ice_tee_import_key(struct device *dev,
lt_key, lt_key_size);
}
+bool qcom_ice_tee_is_available(void)
+{
+ /*
+ * Paired with smp_load_acquire() in qcom_ice_plat_probe().
+ *
+ * This marks the availability of the OPTEE interface informing the
+ * polling ICE driver that the platform supports a TEE.
+ */
+ return !!smp_load_acquire(&__teedev);
+}
+EXPORT_SYMBOL_GPL(qcom_ice_tee_is_available);
+
static bool qcom_ice_tee_has_wrapped_key_support(struct device *dev)
{
struct qcom_ice_tee_private *data = dev_get_drvdata(dev);
@@ -398,5 +414,30 @@ static struct tee_client_driver qcom_ice_tee_driver = {
module_tee_client_driver(qcom_ice_tee_driver);
+static int qcom_ice_plat_probe(struct platform_device *pdev)
+{
+ /* Paired with smp_load_acquire() in qcom_ice_tee_is_available() */
+ smp_store_release(&__teedev, &pdev->dev);
+ return 0;
+}
+
+static const struct platform_device_id qcom_ice_plat_id_table[] = {
+ {
+ .name = "optee",
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(platform, qcom_ice_plat_id_table);
+
+static struct platform_driver qcom_ice_plat_driver = {
+ .probe = qcom_ice_plat_probe,
+ .id_table = qcom_ice_plat_id_table,
+ .driver = {
+ .name = "qcom-ice-plat",
+ },
+};
+
+module_platform_driver(qcom_ice_plat_driver);
+
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Qualcomm ICE TEE driver");
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index 535c8619197b..8dc75c252f52 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -296,6 +296,7 @@ endif
config QCOM_INLINE_CRYPTO_ENGINE
tristate
select QCOM_SCM
+ select QCOM_ICE_TEE
config QCOM_KRYO_L2_ACCESSORS
bool
diff --git a/drivers/soc/qcom/ice.c b/drivers/soc/qcom/ice.c
index 452896b1858f..4844621b7497 100644
--- a/drivers/soc/qcom/ice.c
+++ b/drivers/soc/qcom/ice.c
@@ -18,6 +18,7 @@
#include <linux/platform_device.h>
#include <linux/xarray.h>
+#include <linux/firmware/qcom/qcom_ice_tee.h>
#include <linux/firmware/qcom/qcom_scm.h>
#include <soc/qcom/ice.h>
@@ -132,7 +133,13 @@ static bool qcom_ice_tz_ops_registered(void)
static bool qcom_ice_tz_is_available(void)
{
- return qcom_scm_is_available();
+ /*
+ * Both back-ends should be available before we check for
+ * qcom_ice_tz_ops_registered(), otherwise we could pre-maturely
+ * assume that TZ does not provide any ICE secure interface.
+ */
+ return (qcom_scm_is_available() & qcom_ice_tee_is_available());
+
}
static int qcom_ice_tz_invalidate_key(u32 index)
diff --git a/drivers/tee/optee/ffa_abi.c b/drivers/tee/optee/ffa_abi.c
index 702da7d98fbc..2c0065f3d9e4 100644
--- a/drivers/tee/optee/ffa_abi.c
+++ b/drivers/tee/optee/ffa_abi.c
@@ -1177,6 +1177,14 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
if (rc)
goto err_unregister_devices;
+ /*
+ * Device should only be visible on the platform bus once the
+ * child devices have already been enumerated on the TEE bus.
+ */
+ rc = tee_platform_device_register(optee->teedev, "optee");
+ if (rc)
+ goto err_unregister_devices;
+
INIT_WORK(&optee->rpmb_scan_bus_work, optee_bus_scan_rpmb);
optee->rpmb_intf.notifier_call = optee_rpmb_intf_rdev;
blocking_notifier_chain_register(&optee_rpmb_intf_added,
diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c
index 51624443359b..85ee76173982 100644
--- a/drivers/tee/optee/smc_abi.c
+++ b/drivers/tee/optee/smc_abi.c
@@ -1920,6 +1920,14 @@ static int optee_probe(struct platform_device *pdev)
if (rc)
goto err_disable_shm_cache;
+ /*
+ * Device should only be visible on the platform bus once the
+ * child devices have already been enumerated on the TEE bus.
+ */
+ rc = tee_platform_device_register(optee->teedev, "optee");
+ if (rc)
+ goto err_disable_shm_cache;
+
INIT_WORK(&optee->rpmb_scan_bus_work, optee_bus_scan_rpmb);
optee->rpmb_intf.notifier_call = optee_rpmb_intf_rdev;
blocking_notifier_chain_register(&optee_rpmb_intf_added,
diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c
index 1aac50c7c1de..0d3c266b29c7 100644
--- a/drivers/tee/tee_core.c
+++ b/drivers/tee/tee_core.c
@@ -10,6 +10,7 @@
#include <linux/fs.h>
#include <linux/idr.h>
#include <linux/module.h>
+#include <linux/platform_device.h>
#include <linux/overflow.h>
#include <linux/slab.h>
#include <linux/tee_core.h>
@@ -1225,6 +1226,26 @@ int tee_device_register(struct tee_device *teedev)
}
EXPORT_SYMBOL_GPL(tee_device_register);
+static void plat_tee_free(void *data)
+{
+ struct platform_device *plat_dev = data;
+
+ platform_device_unregister(plat_dev);
+}
+
+int tee_platform_device_register(struct tee_device *teedev, const char *teename)
+{
+ struct platform_device *plat_dev;
+
+ plat_dev = platform_device_register_data(&teedev->dev, teename,
+ PLATFORM_DEVID_NONE, NULL, 0);
+ if (IS_ERR(plat_dev))
+ return PTR_ERR(plat_dev);
+
+ devm_add_action_or_reset(&teedev->dev, plat_tee_free, plat_dev);
+ return 0;
+}
+
void tee_device_put(struct tee_device *teedev)
{
mutex_lock(&teedev->mutex);
diff --git a/include/linux/firmware/qcom/qcom_ice_tee.h b/include/linux/firmware/qcom/qcom_ice_tee.h
new file mode 100644
index 000000000000..a5906c5d4e39
--- /dev/null
+++ b/include/linux/firmware/qcom/qcom_ice_tee.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+#ifndef __QCOM_ICE_TEE
+#define __QCOM_ICE_TEE
+
+bool qcom_ice_tee_is_available(void);
+
+#endif /* __QCOM_ICE_TEE */
diff --git a/include/linux/tee_core.h b/include/linux/tee_core.h
index f993d5118edd..d5310b404c1e 100644
--- a/include/linux/tee_core.h
+++ b/include/linux/tee_core.h
@@ -205,6 +205,15 @@ struct tee_device *tee_device_alloc(const struct tee_desc *teedesc,
*/
int tee_device_register(struct tee_device *teedev);
+/**
+ * tee_platform_device_register() - Registers a TEE platform device
+ * @teedev: Device to register
+ * @teename: Name of the TEE the device represents
+ *
+ * @returns: < 0 on failure
+ */
+int tee_platform_device_register(struct tee_device *teedev, const char *teename);
+
/**
* tee_device_unregister() - Removes a TEE device
* @teedev: Device to unregister
--
2.34.1
next prev parent reply other threads:[~2026-11-11 14:17 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-11 14:17 [PATCH v2 0/6] Add support for a TEE agnostic Inline Crypto Engine service Harshal Dev
2026-11-11 14:17 ` [PATCH v2 1/6] soc: qcom: ice: Add TZ agnostic re-direction functions Harshal Dev
2026-11-11 14:17 ` [PATCH v2 2/6] firmware: qcom_scm: Transition to ICE TZ agnostic operations Harshal Dev
2026-11-11 14:17 ` [PATCH v2 3/6] firmware: qcom: Add a TEE bus based ICE back-end Harshal Dev
2026-11-11 14:17 ` Harshal Dev [this message]
2026-11-11 14:57 ` [PATCH v2 4/6] tee: optee: Register TEE devices on the platform bus Harshal Dev
2026-11-11 14:17 ` [PATCH v2 5/6] soc: qcom: ice: Migrate to the TZ agnostic ICE APIs Harshal Dev
2026-11-11 14:17 ` [PATCH v2 6/6] firmware: qcom: scm: Drop exported ICE wrapper functions Harshal Dev
2026-11-11 14:21 ` [PATCH v2 0/6] Add support for a TEE agnostic Inline Crypto Engine service Harshal Dev
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261111-ice-migrate-tee-svc-v2-4-29d19f6c92ab@oss.qualcomm.com \
--to=harshal.dev@oss.qualcomm.com \
--cc=abelvesa@kernel.org \
--cc=andersson@kernel.org \
--cc=basantk@qti.qualcomm.com \
--cc=ebiggers@kernel.org \
--cc=konradybcio@kernel.org \
--cc=kuldeep.singh@oss.qualcomm.com \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-crypto@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=manivannan.sadhasivam@oss.qualcomm.com \
--cc=neeraj.soni@oss.qualcomm.com \
--cc=selvam.periakaruppan@oss.qualcomm.com \
--cc=sumit.garg@oss.qualcomm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®