[PATCH 2/5] firmware: qcom_scm: Transition to the generic ICE service

From: Harshal Dev

Date: Wed Oct 21 2026 - 11:48:13 EST


Transition the ICE related SCM APIs to the generic ICE service by
registering them with the service's operations and wrapping them in
exported functions with the same signature.

This prepares the ICE driver for eventual migration to the ICE
service from the SCM driver once the TEE bus based back-end becomes
available.

Signed-off-by: Harshal Dev <harshal.dev@xxxxxxxxxxxxxxxx>
---
drivers/firmware/qcom/Kconfig | 1 +
drivers/firmware/qcom/qcom_scm.c | 123 +++++++++++++++++++++++++++++++--------
2 files changed, 100 insertions(+), 24 deletions(-)

diff --git a/drivers/firmware/qcom/Kconfig b/drivers/firmware/qcom/Kconfig
index e2d1c17296c2..6cde1704dbc7 100644
--- a/drivers/firmware/qcom/Kconfig
+++ b/drivers/firmware/qcom/Kconfig
@@ -36,6 +36,7 @@ config QCOM_ICE_SERVICE
config QCOM_SCM
tristate "Qualcomm PAS SCM interface driver" if ARCH_QCOM || COMPILE_TEST
select QCOM_PAS
+ select QCOM_ICE_SERVICE
select QCOM_TZMEM
default y if ARCH_QCOM

diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c
index 43e250faea75..9aeb2cefa77a 100644
--- a/drivers/firmware/qcom/qcom_scm.c
+++ b/drivers/firmware/qcom/qcom_scm.c
@@ -13,6 +13,7 @@
#include <linux/dma-mapping.h>
#include <linux/err.h>
#include <linux/export.h>
+#include <linux/firmware/qcom/qcom_ice.h>
#include <linux/firmware/qcom/qcom_pas.h>
#include <linux/firmware/qcom/qcom_scm.h>
#include <linux/firmware/qcom/qcom_tzmem.h>
@@ -34,6 +35,7 @@

#include <dt-bindings/interrupt-controller/arm-gic.h>

+#include "qcom_ice.h"
#include "qcom_pas.h"
#include "qcom_scm.h"
#include "qcom_tzmem.h"
@@ -1403,13 +1405,18 @@ EXPORT_SYMBOL_GPL(qcom_scm_ocmem_unlock);
* Return: true iff the SCM calls wrapped by qcom_scm_ice_invalidate_key() and
* qcom_scm_ice_set_key() are available.
*/
-bool qcom_scm_ice_available(void)
+static bool __qcom_scm_ice_available(struct device *dev)
{
- return __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_ES,
+ return __qcom_scm_is_call_available(dev, QCOM_SCM_SVC_ES,
QCOM_SCM_ES_INVALIDATE_ICE_KEY) &&
- __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_ES,
+ __qcom_scm_is_call_available(dev, QCOM_SCM_SVC_ES,
QCOM_SCM_ES_CONFIG_SET_ICE_KEY);
}
+
+bool qcom_scm_ice_available(void)
+{
+ return __qcom_scm_ice_available(__scm->dev);
+}
EXPORT_SYMBOL_GPL(qcom_scm_ice_available);

/**
@@ -1424,7 +1431,7 @@ EXPORT_SYMBOL_GPL(qcom_scm_ice_available);
*
* Return: 0 on success; -errno on failure.
*/
-int qcom_scm_ice_invalidate_key(u32 index)
+static int __qcom_scm_ice_invalidate_key(struct device *dev, u32 index)
{
struct qcom_scm_desc desc = {
.svc = QCOM_SCM_SVC_ES,
@@ -1434,7 +1441,12 @@ int qcom_scm_ice_invalidate_key(u32 index)
.owner = ARM_SMCCC_OWNER_SIP,
};

- return qcom_scm_call(__scm->dev, &desc, NULL);
+ return qcom_scm_call(dev, &desc, NULL);
+}
+
+int qcom_scm_ice_invalidate_key(u32 index)
+{
+ return __qcom_scm_ice_invalidate_key(__scm->dev, index);
}
EXPORT_SYMBOL_GPL(qcom_scm_ice_invalidate_key);

@@ -1459,8 +1471,10 @@ EXPORT_SYMBOL_GPL(qcom_scm_ice_invalidate_key);
*
* Return: 0 on success; -errno on failure.
*/
-int qcom_scm_ice_set_key(u32 index, const u8 *key, u32 key_size,
- enum qcom_scm_ice_cipher cipher, u32 data_unit_size)
+static int __qcom_scm_ice_set_key(struct device *dev, u32 index,
+ const u8 *key, u32 key_size,
+ enum qcom_ice_cipher cipher,
+ u32 data_unit_size)
{
struct qcom_scm_desc desc = {
.svc = QCOM_SCM_SVC_ES,
@@ -1485,25 +1499,38 @@ int qcom_scm_ice_set_key(u32 index, const u8 *key, u32 key_size,
memcpy(keybuf, key, key_size);
desc.args[1] = qcom_tzmem_to_phys(keybuf);

- ret = qcom_scm_call(__scm->dev, &desc, NULL);
+ ret = qcom_scm_call(dev, &desc, NULL);

memzero_explicit(keybuf, key_size);

return ret;
}
+
+int qcom_scm_ice_set_key(u32 index, const u8 *key, u32 key_size,
+ enum qcom_scm_ice_cipher cipher, u32 data_unit_size)
+{
+ return __qcom_scm_ice_set_key(__scm->dev, index, key, key_size,
+ (enum qcom_ice_cipher)cipher,
+ data_unit_size);
+}
EXPORT_SYMBOL_GPL(qcom_scm_ice_set_key);

-bool qcom_scm_has_wrapped_key_support(void)
+static bool __qcom_scm_has_wrapped_key_support(struct device *dev)
{
- return __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_ES,
+ return __qcom_scm_is_call_available(dev, QCOM_SCM_SVC_ES,
QCOM_SCM_ES_DERIVE_SW_SECRET) &&
- __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_ES,
+ __qcom_scm_is_call_available(dev, QCOM_SCM_SVC_ES,
QCOM_SCM_ES_GENERATE_ICE_KEY) &&
- __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_ES,
+ __qcom_scm_is_call_available(dev, QCOM_SCM_SVC_ES,
QCOM_SCM_ES_PREPARE_ICE_KEY) &&
- __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_ES,
+ __qcom_scm_is_call_available(dev, QCOM_SCM_SVC_ES,
QCOM_SCM_ES_IMPORT_ICE_KEY);
}
+
+bool qcom_scm_has_wrapped_key_support(void)
+{
+ return __qcom_scm_has_wrapped_key_support(__scm->dev);
+}
EXPORT_SYMBOL_GPL(qcom_scm_has_wrapped_key_support);

/**
@@ -1522,8 +1549,9 @@ EXPORT_SYMBOL_GPL(qcom_scm_has_wrapped_key_support);
*
* Return: 0 on success; -errno on failure.
*/
-int qcom_scm_derive_sw_secret(const u8 *eph_key, size_t eph_key_size,
- u8 *sw_secret, size_t sw_secret_size)
+static int __qcom_scm_derive_sw_secret(struct device *dev,
+ const u8 *eph_key, size_t eph_key_size,
+ u8 *sw_secret, size_t sw_secret_size)
{
struct qcom_scm_desc desc = {
.svc = QCOM_SCM_SVC_ES,
@@ -1552,7 +1580,7 @@ int qcom_scm_derive_sw_secret(const u8 *eph_key, size_t eph_key_size,
desc.args[2] = qcom_tzmem_to_phys(sw_secret_buf);
desc.args[3] = sw_secret_size;

- ret = qcom_scm_call(__scm->dev, &desc, NULL);
+ ret = qcom_scm_call(dev, &desc, NULL);
if (!ret)
memcpy(sw_secret, sw_secret_buf, sw_secret_size);

@@ -1560,6 +1588,13 @@ int qcom_scm_derive_sw_secret(const u8 *eph_key, size_t eph_key_size,
memzero_explicit(sw_secret_buf, sw_secret_size);
return ret;
}
+
+int qcom_scm_derive_sw_secret(const u8 *eph_key, size_t eph_key_size,
+ u8 *sw_secret, size_t sw_secret_size)
+{
+ return __qcom_scm_derive_sw_secret(__scm->dev, eph_key, eph_key_size,
+ sw_secret, sw_secret_size);
+}
EXPORT_SYMBOL_GPL(qcom_scm_derive_sw_secret);

/**
@@ -1573,7 +1608,8 @@ EXPORT_SYMBOL_GPL(qcom_scm_derive_sw_secret);
*
* Return: 0 on success; -errno on failure.
*/
-int qcom_scm_generate_ice_key(u8 *lt_key, size_t lt_key_size)
+static int __qcom_scm_generate_ice_key(struct device *dev,
+ u8 *lt_key, size_t lt_key_size)
{
struct qcom_scm_desc desc = {
.svc = QCOM_SCM_SVC_ES,
@@ -1592,13 +1628,18 @@ int qcom_scm_generate_ice_key(u8 *lt_key, size_t lt_key_size)
desc.args[0] = qcom_tzmem_to_phys(lt_key_buf);
desc.args[1] = lt_key_size;

- ret = qcom_scm_call(__scm->dev, &desc, NULL);
+ ret = qcom_scm_call(dev, &desc, NULL);
if (!ret)
memcpy(lt_key, lt_key_buf, lt_key_size);

memzero_explicit(lt_key_buf, lt_key_size);
return ret;
}
+
+int qcom_scm_generate_ice_key(u8 *lt_key, size_t lt_key_size)
+{
+ return __qcom_scm_generate_ice_key(__scm->dev, lt_key, lt_key_size);
+}
EXPORT_SYMBOL_GPL(qcom_scm_generate_ice_key);

/**
@@ -1614,8 +1655,9 @@ EXPORT_SYMBOL_GPL(qcom_scm_generate_ice_key);
*
* Return: 0 on success; -errno on failure.
*/
-int qcom_scm_prepare_ice_key(const u8 *lt_key, size_t lt_key_size,
- u8 *eph_key, size_t eph_key_size)
+static int __qcom_scm_prepare_ice_key(struct device *dev,
+ const u8 *lt_key, size_t lt_key_size,
+ u8 *eph_key, size_t eph_key_size)
{
struct qcom_scm_desc desc = {
.svc = QCOM_SCM_SVC_ES,
@@ -1644,7 +1686,7 @@ int qcom_scm_prepare_ice_key(const u8 *lt_key, size_t lt_key_size,
desc.args[2] = qcom_tzmem_to_phys(eph_key_buf);
desc.args[3] = eph_key_size;

- ret = qcom_scm_call(__scm->dev, &desc, NULL);
+ ret = qcom_scm_call(dev, &desc, NULL);
if (!ret)
memcpy(eph_key, eph_key_buf, eph_key_size);

@@ -1652,6 +1694,13 @@ int qcom_scm_prepare_ice_key(const u8 *lt_key, size_t lt_key_size,
memzero_explicit(eph_key_buf, eph_key_size);
return ret;
}
+
+int qcom_scm_prepare_ice_key(const u8 *lt_key, size_t lt_key_size,
+ u8 *eph_key, size_t eph_key_size)
+{
+ return __qcom_scm_prepare_ice_key(__scm->dev, lt_key, lt_key_size,
+ eph_key, eph_key_size);
+}
EXPORT_SYMBOL_GPL(qcom_scm_prepare_ice_key);

/**
@@ -1667,8 +1716,9 @@ EXPORT_SYMBOL_GPL(qcom_scm_prepare_ice_key);
*
* Return: 0 on success; -errno on failure.
*/
-int qcom_scm_import_ice_key(const u8 *raw_key, size_t raw_key_size,
- u8 *lt_key, size_t lt_key_size)
+static int __qcom_scm_import_ice_key(struct device *dev,
+ const u8 *raw_key, size_t raw_key_size,
+ u8 *lt_key, size_t lt_key_size)
{
struct qcom_scm_desc desc = {
.svc = QCOM_SCM_SVC_ES,
@@ -1697,7 +1747,7 @@ int qcom_scm_import_ice_key(const u8 *raw_key, size_t raw_key_size,
desc.args[2] = qcom_tzmem_to_phys(lt_key_buf);
desc.args[3] = lt_key_size;

- ret = qcom_scm_call(__scm->dev, &desc, NULL);
+ ret = qcom_scm_call(dev, &desc, NULL);
if (!ret)
memcpy(lt_key, lt_key_buf, lt_key_size);

@@ -1705,8 +1755,27 @@ int qcom_scm_import_ice_key(const u8 *raw_key, size_t raw_key_size,
memzero_explicit(lt_key_buf, lt_key_size);
return ret;
}
+
+int qcom_scm_import_ice_key(const u8 *raw_key, size_t raw_key_size,
+ u8 *lt_key, size_t lt_key_size)
+{
+ return __qcom_scm_import_ice_key(__scm->dev, raw_key, raw_key_size,
+ lt_key, lt_key_size);
+}
EXPORT_SYMBOL_GPL(qcom_scm_import_ice_key);

+static struct qcom_ice_ops qcom_ice_ops_scm = {
+ .drv_name = "qcom_scm",
+ .is_ice_available = __qcom_scm_ice_available,
+ .ice_invalidate_key = __qcom_scm_ice_invalidate_key,
+ .ice_set_key = __qcom_scm_ice_set_key,
+ .ice_has_wrapped_key_support = __qcom_scm_has_wrapped_key_support,
+ .ice_derive_sw_secret = __qcom_scm_derive_sw_secret,
+ .ice_generate_key = __qcom_scm_generate_ice_key,
+ .ice_prepare_key = __qcom_scm_prepare_ice_key,
+ .ice_import_key = __qcom_scm_import_ice_key,
+};
+
/**
* qcom_scm_hdcp_available() - Check if secure environment supports HDCP.
*
@@ -2836,6 +2905,11 @@ static int qcom_scm_probe(struct platform_device *pdev)
qcom_pas_ops_register(&qcom_pas_ops_scm);
}

+ if (__qcom_scm_ice_available(scm->dev)) {
+ qcom_ice_ops_scm.dev = scm->dev;
+ qcom_ice_svc_ops_register(&qcom_ice_ops_scm);
+ }
+
/*
* If "download mode" is requested, from this point on warmboot
* will cause the boot stages to enter download mode, unless
@@ -2876,6 +2950,7 @@ static void qcom_scm_shutdown(struct platform_device *pdev)
/* Clean shutdown, disable download mode to allow normal restart */
qcom_scm_set_download_mode(__scm, QCOM_DLOAD_NODUMP);
qcom_pas_ops_unregister();
+ qcom_ice_svc_ops_unregister(&qcom_ice_ops_scm);
}

static const struct of_device_id qcom_scm_dt_match[] = {

--
2.34.1