[PATCH v2 01/10] firmware: arm_scmi: Add scmi_get_base_info()

From: Geert Uytterhoeven

Date: Wed Jul 08 2026 - 06:31:03 EST


Currently non-SCMI drivers cannot find out what the specific versions of
each SCMI provider implementation on the running system are.

However, different versions may use different ABIs (e.g. different clock
IDs), provide different abstractions, or behave different, requiring
remapping or workarounds in other drivers.

Add a public function to obtain base protocol information for the
selected SCMI provider. This will be used by the R-Car X5H Clock Pulse
Generator and Module Controller drivers, to map hardware descriptions in
DT to SCMI abstractions provided by the SCMI implementation present.

Signed-off-by: Geert Uytterhoeven <geert+renesas@xxxxxxxxx>
---
v2:
- Add that SCMI may provide different abstractions,
- Add missing asterisk to blank kerneldoc line,
- Return -EPROBE_DEFER or -EOPNOTSUPP instead of -ENOENT.
---
drivers/firmware/arm_scmi/driver.c | 33 ++++++++++++++++++++++++++++++
include/linux/scmi_protocol.h | 8 ++++++++
2 files changed, 41 insertions(+)

diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 3e0d975ec94c4485..80a29c3289f0a841 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -3504,6 +3504,39 @@ int scmi_inflight_count(const struct scmi_handle *handle)
}
}

+/**
+ * scmi_get_base_info() - Get SCMI base protocol information
+ *
+ * @of_node: pointer to a device node for an SCMI provider
+ * @version: pointer to write base protocol information
+ *
+ * Check if an SCMI device has been instantiated for the passed device node
+ * pointer, and, if found, return its base info.
+ *
+ * Return: 0 on Success,
+ * -EPROBE_DEFER if the SCMI provider is not ready yet,
+ * -EOPNOTSUPP if SCMI support is disabled.
+ */
+int scmi_get_base_info(struct device_node *of_node,
+ struct scmi_base_info *version)
+{
+ int ret = -EPROBE_DEFER;
+ struct scmi_info *info;
+
+ mutex_lock(&scmi_list_mutex);
+ list_for_each_entry(info, &scmi_list, node) {
+ if (info->dev->of_node == of_node) {
+ *version = info->version;
+ ret = 0;
+ break;
+ }
+ }
+ mutex_unlock(&scmi_list_mutex);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(scmi_get_base_info);
+
static int __init scmi_driver_init(void)
{
scmi_quirks_initialize();
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index 5ab73b1ab9aa4fa8..fd2d648964f68f53 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -971,6 +971,8 @@ struct scmi_driver {
int scmi_driver_register(struct scmi_driver *driver,
struct module *owner, const char *mod_name);
void scmi_driver_unregister(struct scmi_driver *driver);
+int scmi_get_base_info(struct device_node *of_node,
+ struct scmi_base_info *version);
#else
static inline int
scmi_driver_register(struct scmi_driver *driver, struct module *owner,
@@ -980,6 +982,12 @@ scmi_driver_register(struct scmi_driver *driver, struct module *owner,
}

static inline void scmi_driver_unregister(struct scmi_driver *driver) {}
+
+static inline int scmi_get_base_info(struct device_node *of_node,
+ struct scmi_base_info *version)
+{
+ return -EOPNOTSUPP;
+}
#endif /* CONFIG_ARM_SCMI_PROTOCOL */

#define scmi_register(driver) \
--
2.43.0