summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rini <[email protected]>2025-10-24 12:09:02 -0600
committerTom Rini <[email protected]>2025-10-24 13:47:50 -0600
commitfd976ff3a233ae7c6a9f5bec790b02bbbf57bb24 (patch)
tree1bffd9388bcc9856cb9451c2034ef18158f356b3
parentfae6c54d238279bf79c66ca65330425dff2c952f (diff)
parentac9b02dd1028d14b6326970c93dfc3c50daa16f1 (diff)
Merge patch series "firmware: scmi: Support SCMI LMM/CPU protocol for i.MX95"
Peng Fan (OSS) <[email protected]> says: i.MX95 System Manager(SM) implements Logical Machine Management(LMM) and CPU protocol to manage Logical Machine(LM) and CPUs(eg, M7). To manage M7 in a separate LM or in same LM as U-Boot/Linux itself. LMM APIs and CPU APIs are needed. When M7 is in LM 'lm-m7', and this LM is managable by 'uboot-lm', U-Boot could use LMM_BOOT, LMM_SHUTDOWN and etc to manage 'lm-m7'. If in same LM, use CPU_START, CPU_STOP, CPU_RESET_VECTOR_SET and etc to manage M7. Both LMM/CPU APIs will be used by remoteproc driver. The documentation could be found in Linux Kernel: drivers/firmware/arm_scmi/vendors/imx/imx95.rst Link: https://lore.kernel.org/r/[email protected]
-rw-r--r--drivers/firmware/scmi/Kconfig8
-rw-r--r--drivers/firmware/scmi/Makefile1
-rw-r--r--drivers/firmware/scmi/scmi_agent-uclass.c40
-rw-r--r--drivers/firmware/scmi/vendors/imx/Kconfig15
-rw-r--r--drivers/firmware/scmi/vendors/imx/Makefile8
-rw-r--r--drivers/firmware/scmi/vendors/imx/imx-sm-cpu.c179
-rw-r--r--drivers/firmware/scmi/vendors/imx/imx-sm-lmm.c213
-rw-r--r--include/scmi_agent-uclass.h16
-rw-r--r--include/scmi_nxp_protocols.h73
-rw-r--r--include/scmi_protocols.h3
10 files changed, 552 insertions, 4 deletions
diff --git a/drivers/firmware/scmi/Kconfig b/drivers/firmware/scmi/Kconfig
index 8cf85f0d7a1..33e089c460b 100644
--- a/drivers/firmware/scmi/Kconfig
+++ b/drivers/firmware/scmi/Kconfig
@@ -41,3 +41,11 @@ config SCMI_AGENT_OPTEE
help
Enable the SCMI communication channel based on OP-TEE transport
for compatible "linaro,scmi-optee".
+
+config SCMI_ID_VENDOR_80
+ bool
+
+config SCMI_ID_VENDOR_82
+ bool
+
+source "drivers/firmware/scmi/vendors/imx/Kconfig"
diff --git a/drivers/firmware/scmi/Makefile b/drivers/firmware/scmi/Makefile
index dae42863589..6129726f817 100644
--- a/drivers/firmware/scmi/Makefile
+++ b/drivers/firmware/scmi/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_SCMI_AGENT_MAILBOX) += mailbox_agent.o
obj-$(CONFIG_SCMI_AGENT_OPTEE) += optee_agent.o
obj-$(CONFIG_SCMI_POWER_DOMAIN) += pwdom.o
obj-$(CONFIG_SANDBOX) += sandbox-scmi_agent.o sandbox-scmi_devices.o
+obj-y += vendors/imx/
diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c b/drivers/firmware/scmi/scmi_agent-uclass.c
index 69a277e8786..ad825d66da2 100644
--- a/drivers/firmware/scmi/scmi_agent-uclass.c
+++ b/drivers/firmware/scmi/scmi_agent-uclass.c
@@ -86,21 +86,41 @@ struct udevice *scmi_get_protocol(struct udevice *dev,
case SCMI_PROTOCOL_ID_BASE:
proto = priv->base_dev;
break;
+#if IS_ENABLED(CONFIG_SCMI_POWER_DOMAIN)
case SCMI_PROTOCOL_ID_POWER_DOMAIN:
proto = priv->pwdom_dev;
break;
+#endif
+#if IS_ENABLED(CONFIG_CLK_SCMI)
case SCMI_PROTOCOL_ID_CLOCK:
proto = priv->clock_dev;
break;
+#endif
+#if IS_ENABLED(CONFIG_RESET_SCMI)
case SCMI_PROTOCOL_ID_RESET_DOMAIN:
proto = priv->resetdom_dev;
break;
+#endif
+#if IS_ENABLED(CONFIG_DM_REGULATOR_SCMI)
case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN:
proto = priv->voltagedom_dev;
break;
+#endif
+#if IS_ENABLED(CONFIG_PINCTRL_IMX_SCMI)
case SCMI_PROTOCOL_ID_PINCTRL:
proto = priv->pinctrl_dev;
break;
+#endif
+#if IS_ENABLED(CONFIG_SCMI_ID_VENDOR_80)
+ case SCMI_PROTOCOL_ID_VENDOR_80:
+ proto = priv->vendor_dev_80;
+ break;
+#endif
+#if IS_ENABLED(CONFIG_SCMI_ID_VENDOR_82)
+ case SCMI_PROTOCOL_ID_VENDOR_82:
+ proto = priv->vendor_dev_82;
+ break;
+#endif
default:
dev_err(dev, "Protocol not supported\n");
proto = NULL;
@@ -139,21 +159,41 @@ static int scmi_add_protocol(struct udevice *dev,
case SCMI_PROTOCOL_ID_BASE:
priv->base_dev = proto;
break;
+#if IS_ENABLED(CONFIG_SCMI_POWER_DOMAIN)
case SCMI_PROTOCOL_ID_POWER_DOMAIN:
priv->pwdom_dev = proto;
break;
+#endif
+#if IS_ENABLED(CONFIG_CLK_SCMI)
case SCMI_PROTOCOL_ID_CLOCK:
priv->clock_dev = proto;
break;
+#endif
+#if IS_ENABLED(CONFIG_RESET_SCMI)
case SCMI_PROTOCOL_ID_RESET_DOMAIN:
priv->resetdom_dev = proto;
break;
+#endif
+#if IS_ENABLED(CONFIG_DM_REGULATOR_SCMI)
case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN:
priv->voltagedom_dev = proto;
break;
+#endif
+#if IS_ENABLED(CONFIG_PINCTRL_IMX_SCMI)
case SCMI_PROTOCOL_ID_PINCTRL:
priv->pinctrl_dev = proto;
break;
+#endif
+#if IS_ENABLED(CONFIG_SCMI_ID_VENDOR_80)
+ case SCMI_PROTOCOL_ID_VENDOR_80:
+ priv->vendor_dev_80 = proto;
+ break;
+#endif
+#if IS_ENABLED(CONFIG_SCMI_ID_VENDOR_82)
+ case SCMI_PROTOCOL_ID_VENDOR_82:
+ priv->vendor_dev_82 = proto;
+ break;
+#endif
default:
dev_err(dev, "Protocol not supported\n");
return -EPROTO;
diff --git a/drivers/firmware/scmi/vendors/imx/Kconfig b/drivers/firmware/scmi/vendors/imx/Kconfig
new file mode 100644
index 00000000000..16850502bbb
--- /dev/null
+++ b/drivers/firmware/scmi/vendors/imx/Kconfig
@@ -0,0 +1,15 @@
+config IMX_SM_CPU
+ bool "Enable i.MX System Manager CPU API"
+ depends on ARCH_IMX9 && SCMI_FIRMWARE
+ select SCMI_ID_VENDOR_82
+ help
+ If you say Y here to enable i.MX System Manager CPU
+ API to work on some NXP i.MX processors.
+
+config IMX_SM_LMM
+ bool "Enable i.MX System Manager Logical Machine API"
+ depends on ARCH_IMX9 && SCMI_FIRMWARE
+ select SCMI_ID_VENDOR_80
+ help
+ If you say Y here to enable i.MX System Manager Logical Machine
+ API to work on some NXP i.MX processors.
diff --git a/drivers/firmware/scmi/vendors/imx/Makefile b/drivers/firmware/scmi/vendors/imx/Makefile
new file mode 100644
index 00000000000..59ff8640dc1
--- /dev/null
+++ b/drivers/firmware/scmi/vendors/imx/Makefile
@@ -0,0 +1,8 @@
+#
+# Copyright 2025 NXP
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+obj-$(CONFIG_IMX_SM_CPU) += imx-sm-cpu.o
+obj-$(CONFIG_IMX_SM_LMM) += imx-sm-lmm.o
diff --git a/drivers/firmware/scmi/vendors/imx/imx-sm-cpu.c b/drivers/firmware/scmi/vendors/imx/imx-sm-cpu.c
new file mode 100644
index 00000000000..28dfac642ec
--- /dev/null
+++ b/drivers/firmware/scmi/vendors/imx/imx-sm-cpu.c
@@ -0,0 +1,179 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * i.MX SCMI CPU protocol
+ *
+ * Copyright 2025 NXP
+ */
+
+#include <compiler.h>
+#include <dm.h>
+#include <dm/device_compat.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <misc.h>
+#include <scmi_agent.h>
+#include <scmi_agent-uclass.h>
+#include <scmi_protocols.h>
+#include <scmi_nxp_protocols.h>
+
+enum scmi_imx_cpu_protocol_cmd {
+ SCMI_IMX_CPU_ATTRIBUTES = 0x3,
+ SCMI_IMX_CPU_START = 0x4,
+ SCMI_IMX_CPU_STOP = 0x5,
+ SCMI_IMX_CPU_RESET_VECTOR_SET = 0x6,
+ SCMI_IMX_CPU_INFO_GET = 0xC,
+};
+
+struct scmi_imx_cpu_priv {
+ u32 nr_cpu;
+};
+
+struct scmi_imx_cpu_reset_vector_set_in {
+ __le32 cpuid;
+#define CPU_VEC_FLAGS_RESUME BIT(31)
+#define CPU_VEC_FLAGS_START BIT(30)
+#define CPU_VEC_FLAGS_BOOT BIT(29)
+ __le32 flags;
+ __le32 resetvectorlow;
+ __le32 resetvectorhigh;
+};
+
+struct scmi_imx_cpu_info_get_out {
+ __le32 status;
+#define CPU_RUN_MODE_START 0
+#define CPU_RUN_MODE_HOLD 1
+#define CPU_RUN_MODE_STOP 2
+#define CPU_RUN_MODE_SLEEP 3
+ __le32 runmode;
+ __le32 sleepmode;
+ __le32 resetvectorlow;
+ __le32 resetvectorhigh;
+};
+
+int scmi_imx_cpu_start(struct udevice *dev, u32 cpuid, bool start)
+{
+ s32 status;
+ struct scmi_msg msg = {
+ .protocol_id = SCMI_PROTOCOL_ID_VENDOR_82,
+ .message_id = SCMI_IMX_CPU_STOP,
+ .in_msg = (u8 *)&cpuid,
+ .in_msg_sz = sizeof(cpuid),
+ .out_msg = (u8 *)&status,
+ .out_msg_sz = sizeof(status),
+ };
+ int ret;
+
+ if (!dev)
+ return -EINVAL;
+
+ if (start)
+ msg.message_id = SCMI_IMX_CPU_START;
+
+ ret = devm_scmi_process_msg(dev, &msg);
+ if (ret)
+ return ret;
+
+ if (status)
+ return scmi_to_linux_errno(status);
+
+ return 0;
+}
+
+int scmi_imx_cpu_reset_vector_set(struct udevice *dev, u32 cpuid, u32 flags, u64 vector,
+ bool start, bool boot, bool resume)
+{
+ struct scmi_imx_cpu_reset_vector_set_in in;
+ s32 status;
+ struct scmi_msg msg = {
+ .protocol_id = SCMI_PROTOCOL_ID_VENDOR_82,
+ .message_id = SCMI_IMX_CPU_RESET_VECTOR_SET,
+ .in_msg = (u8 *)&in,
+ .in_msg_sz = sizeof(in),
+ .out_msg = (u8 *)&status,
+ .out_msg_sz = sizeof(status),
+ };
+ int ret;
+
+ if (!dev)
+ return -EINVAL;
+
+ in.cpuid = cpu_to_le32(cpuid);
+ in.flags = cpu_to_le32(0);
+ if (start)
+ in.flags |= CPU_VEC_FLAGS_START;
+ if (boot)
+ in.flags |= CPU_VEC_FLAGS_BOOT;
+ if (resume)
+ in.flags |= CPU_VEC_FLAGS_RESUME;
+ in.resetvectorlow = cpu_to_le32(lower_32_bits(vector));
+ in.resetvectorhigh = cpu_to_le32(upper_32_bits(vector));
+
+ ret = devm_scmi_process_msg(dev, &msg);
+ if (ret)
+ return ret;
+
+ if (status)
+ return scmi_to_linux_errno(status);
+
+ return 0;
+}
+
+int scmi_imx_cpu_started(struct udevice *dev, u32 cpuid, bool *started)
+{
+ struct scmi_imx_cpu_info_get_out out;
+ u32 mode;
+ s32 status;
+ struct scmi_msg msg = {
+ .protocol_id = SCMI_PROTOCOL_ID_VENDOR_82,
+ .message_id = SCMI_IMX_CPU_INFO_GET,
+ .in_msg = (u8 *)&cpuid,
+ .in_msg_sz = sizeof(cpuid),
+ .out_msg = (u8 *)&out,
+ .out_msg_sz = sizeof(out),
+ };
+ int ret;
+
+ if (!dev)
+ return -EINVAL;
+
+ ret = devm_scmi_process_msg(dev, &msg);
+ if (ret)
+ return ret;
+
+ status = cpu_to_le32(out.status);
+ if (status)
+ return scmi_to_linux_errno(status);
+
+ mode = le32_to_cpu(out.runmode);
+ if (mode == CPU_RUN_MODE_START || mode == CPU_RUN_MODE_SLEEP)
+ *started = true;
+
+ return 0;
+}
+
+static int scmi_imx_cpu_probe(struct udevice *dev)
+{
+ int ret;
+
+ ret = devm_scmi_of_get_channel(dev);
+ if (ret) {
+ dev_err(dev, "failed to get channel (%d)\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+U_BOOT_DRIVER(scmi_imx_cpu) = {
+ .name = "scmi_imx_cpu",
+ .id = UCLASS_SCMI_BASE,
+ .probe = scmi_imx_cpu_probe,
+ .priv_auto = sizeof(struct scmi_imx_cpu_priv),
+};
+
+static struct scmi_proto_match match[] = {
+ { .proto_id = SCMI_PROTOCOL_ID_VENDOR_82},
+ { /* Sentinel */ }
+};
+
+U_BOOT_SCMI_PROTO_DRIVER(scmi_imx_cpu, match);
diff --git a/drivers/firmware/scmi/vendors/imx/imx-sm-lmm.c b/drivers/firmware/scmi/vendors/imx/imx-sm-lmm.c
new file mode 100644
index 00000000000..2fd791ca853
--- /dev/null
+++ b/drivers/firmware/scmi/vendors/imx/imx-sm-lmm.c
@@ -0,0 +1,213 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * i.MX SCMI LMM protocol
+ *
+ * Copyright 2025 NXP
+ */
+
+#include <compiler.h>
+#include <dm.h>
+#include <dm/device_compat.h>
+#include <linux/types.h>
+#include <misc.h>
+#include <scmi_agent.h>
+#include <scmi_agent-uclass.h>
+#include <scmi_protocols.h>
+#include <scmi_nxp_protocols.h>
+
+enum scmi_imx_lmm_protocol_cmd {
+ SCMI_IMX_LMM_ATTRIBUTES = 0x3,
+ SCMI_IMX_LMM_BOOT = 0x4,
+ SCMI_IMX_LMM_RESET = 0x5,
+ SCMI_IMX_LMM_SHUTDOWN = 0x6,
+ SCMI_IMX_LMM_WAKE = 0x7,
+ SCMI_IMX_LMM_SUSPEND = 0x8,
+ SCMI_IMX_LMM_NOTIFY = 0x9,
+ SCMI_IMX_LMM_RESET_REASON = 0xA,
+ SCMI_IMX_LMM_POWER_ON = 0xB,
+ SCMI_IMX_LMM_RESET_VECTOR_SET = 0xC,
+};
+
+struct scmi_imx_lmm_priv {
+ u32 nr_lmm;
+};
+
+struct scmi_msg_imx_lmm_attributes_out {
+ __le32 status;
+ __le32 lmid;
+ __le32 attributes;
+ __le32 state;
+ __le32 errstatus;
+ u8 name[LMM_MAX_NAME];
+};
+
+struct scmi_imx_lmm_reset_vector_set_in {
+ __le32 lmid;
+ __le32 cpuid;
+ __le32 flags; /* reserved for future extension */
+ __le32 resetvectorlow;
+ __le32 resetvectorhigh;
+};
+
+struct scmi_imx_lmm_shutdown_in {
+ __le32 lmid;
+#define SCMI_IMX_LMM_SHUTDOWN_GRACEFUL BIT(0)
+ __le32 flags;
+};
+
+int scmi_imx_lmm_info(struct udevice *dev, u32 lmid, struct scmi_imx_lmm_info *info)
+{
+ struct scmi_msg_imx_lmm_attributes_out out;
+ s32 status;
+ struct scmi_msg msg = {
+ .protocol_id = SCMI_PROTOCOL_ID_VENDOR_80,
+ .message_id = SCMI_IMX_LMM_ATTRIBUTES,
+ .in_msg = (u8 *)&lmid,
+ .in_msg_sz = sizeof(lmid),
+ .out_msg = (u8 *)&out,
+ .out_msg_sz = sizeof(out),
+ };
+ int ret;
+
+ if (!dev)
+ return -EINVAL;
+
+ ret = devm_scmi_process_msg(dev, &msg);
+ if (ret)
+ return ret;
+
+ status = cpu_to_le32(out.status);
+ if (status)
+ return scmi_to_linux_errno(status);
+
+ info->lmid = le32_to_cpu(out.lmid);
+ info->state = le32_to_cpu(out.state);
+ info->errstatus = le32_to_cpu(out.errstatus);
+ strcpy(info->name, out.name);
+ dev_dbg(dev, "i.MX LMM: Logical Machine(%d), name: %s\n",
+ info->lmid, info->name);
+
+ return ret;
+}
+
+int scmi_imx_lmm_power_boot(struct udevice *dev, u32 lmid, bool boot)
+{
+ s32 status;
+ struct scmi_msg msg = {
+ .protocol_id = SCMI_PROTOCOL_ID_VENDOR_80,
+ .message_id = SCMI_IMX_LMM_POWER_ON,
+ .in_msg = (u8 *)&lmid,
+ .in_msg_sz = sizeof(lmid),
+ .out_msg = (u8 *)&status,
+ .out_msg_sz = sizeof(status),
+ };
+ int ret;
+
+ if (!dev)
+ return -EINVAL;
+
+ if (boot)
+ msg.message_id = SCMI_IMX_LMM_BOOT;
+
+ ret = devm_scmi_process_msg(dev, &msg);
+ if (ret)
+ return ret;
+
+ if (status)
+ return scmi_to_linux_errno(status);
+
+ return 0;
+}
+
+int scmi_imx_lmm_reset_vector_set(struct udevice *dev, u32 lmid, u32 cpuid, u32 flags, u64 vector)
+{
+ struct scmi_imx_lmm_reset_vector_set_in in;
+ s32 status;
+ struct scmi_msg msg = {
+ .protocol_id = SCMI_PROTOCOL_ID_VENDOR_80,
+ .message_id = SCMI_IMX_LMM_RESET_VECTOR_SET,
+ .in_msg = (u8 *)&in,
+ .in_msg_sz = sizeof(in),
+ .out_msg = (u8 *)&status,
+ .out_msg_sz = sizeof(status),
+ };
+ int ret;
+
+ if (!dev)
+ return -EINVAL;
+
+ in.lmid = lmid;
+ in.cpuid = cpuid;
+ in.flags = flags;
+ in.resetvectorlow = vector & 0xFFFFFFFF;
+ in.resetvectorhigh = vector >> 32;
+
+ ret = devm_scmi_process_msg(dev, &msg);
+ if (ret)
+ return ret;
+
+ if (status)
+ return scmi_to_linux_errno(status);
+
+ return 0;
+}
+
+int scmi_imx_lmm_shutdown(struct udevice *dev, u32 lmid, bool flags)
+{
+ struct scmi_imx_lmm_shutdown_in in;
+ s32 status;
+ struct scmi_msg msg = {
+ .protocol_id = SCMI_PROTOCOL_ID_VENDOR_80,
+ .message_id = SCMI_IMX_LMM_SHUTDOWN,
+ .in_msg = (u8 *)&in,
+ .in_msg_sz = sizeof(in),
+ .out_msg = (u8 *)&status,
+ .out_msg_sz = sizeof(status),
+ };
+ int ret;
+
+ if (!dev)
+ return -EINVAL;
+
+ in.lmid = lmid;
+ if (flags & SCMI_IMX_LMM_SHUTDOWN_GRACEFUL)
+ in.flags = cpu_to_le32(SCMI_IMX_LMM_SHUTDOWN_GRACEFUL);
+ else
+ in.flags = cpu_to_le32(0);
+
+ ret = devm_scmi_process_msg(dev, &msg);
+ if (ret)
+ return ret;
+
+ if (status)
+ return scmi_to_linux_errno(status);
+
+ return 0;
+}
+
+static int scmi_imx_lmm_probe(struct udevice *dev)
+{
+ int ret;
+
+ ret = devm_scmi_of_get_channel(dev);
+ if (ret) {
+ dev_err(dev, "failed to get channel (%d)\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+U_BOOT_DRIVER(scmi_imx_lmm) = {
+ .name = "scmi_imx_lmm",
+ .id = UCLASS_SCMI_BASE,
+ .probe = scmi_imx_lmm_probe,
+ .priv_auto = sizeof(struct scmi_imx_lmm_priv),
+};
+
+static struct scmi_proto_match match[] = {
+ { .proto_id = SCMI_PROTOCOL_ID_VENDOR_80},
+ { /* Sentinel */ }
+};
+
+U_BOOT_SCMI_PROTO_DRIVER(scmi_imx_lmm, match);
diff --git a/include/scmi_agent-uclass.h b/include/scmi_agent-uclass.h
index d6586eb3ff9..9b36d3ae67b 100644
--- a/include/scmi_agent-uclass.h
+++ b/include/scmi_agent-uclass.h
@@ -40,11 +40,27 @@ struct scmi_agent_priv {
u8 *agent_name;
u32 agent_id;
struct udevice *base_dev;
+#if IS_ENABLED(CONFIG_SCMI_POWER_DOMAIN)
struct udevice *pwdom_dev;
+#endif
+#if IS_ENABLED(CONFIG_CLK_SCMI)
struct udevice *clock_dev;
+#endif
+#if IS_ENABLED(CONFIG_RESET_SCMI)
struct udevice *resetdom_dev;
+#endif
+#if IS_ENABLED(CONFIG_DM_REGULATOR_SCMI)
struct udevice *voltagedom_dev;
+#endif
+#if IS_ENABLED(CONFIG_PINCTRL_IMX_SCMI)
struct udevice *pinctrl_dev;
+#endif
+#if IS_ENABLED(CONFIG_SCMI_ID_VENDOR_80)
+ struct udevice *vendor_dev_80;
+#endif
+#if IS_ENABLED(CONFIG_SCMI_ID_VENDOR_82)
+ struct udevice *vendor_dev_82;
+#endif
};
static inline u32 scmi_version(struct udevice *dev)
diff --git a/include/scmi_nxp_protocols.h b/include/scmi_nxp_protocols.h
index fe6ecd6a7cf..c17f3663eba 100644
--- a/include/scmi_nxp_protocols.h
+++ b/include/scmi_nxp_protocols.h
@@ -9,9 +9,9 @@
#include <asm/types.h>
#include <linux/bitops.h>
-enum scmi_imx_protocol {
- SCMI_IMX_PROTOCOL_ID_MISC = 0x84,
-};
+#define SCMI_PROTOCOL_ID_IMX_LMM 0x80
+#define SCMI_PROTOCOL_ID_IMX_CPU 0x82
+#define SCMI_PROTOCOL_ID_IMX_MISC 0x84
#define SCMI_PAYLOAD_LEN 100
@@ -52,4 +52,71 @@ struct scmi_imx_misc_reset_reason_out {
u32 extInfo[MISC_MAX_EXTINFO];
};
+#define LMM_ID_DISCOVER 0xFFFFFFFFU
+#define LMM_MAX_NAME 16
+
+enum scmi_imx_lmm_state {
+ LMM_STATE_LM_OFF,
+ LMM_STATE_LM_ON,
+ LMM_STATE_LM_SUSPEND,
+ LMM_STATE_LM_POWERED,
+};
+
+struct scmi_imx_lmm_info {
+ u32 lmid;
+ enum scmi_imx_lmm_state state;
+ u32 errstatus;
+ u8 name[LMM_MAX_NAME];
+};
+
+#if IS_ENABLED(CONFIG_IMX_SM_LMM)
+int scmi_imx_lmm_info(struct udevice *dev, u32 lmid, struct scmi_imx_lmm_info *info);
+int scmi_imx_lmm_power_boot(struct udevice *dev, u32 lmid, bool boot);
+int scmi_imx_lmm_reset_vector_set(struct udevice *dev, u32 lmid, u32 cpuid, u32 flags, u64 vector);
+int scmi_imx_lmm_shutdown(struct udevice *dev, u32 lmid, bool flags);
+#else
+static inline int scmi_imx_lmm_info(struct udevice *dev, u32 lmid, struct scmi_imx_lmm_info *info)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline int scmi_imx_lmm_power_boot(struct udevice *dev, u32 lmid, bool boot)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline int
+scmi_imx_lmm_reset_vector_set(struct udevice *dev, u32 lmid, u32 cpuid, u32 flags, u64 vector)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline int scmi_imx_lmm_shutdown(struct udevice *dev, u32 lmid, bool flags)
+{
+ return -EOPNOTSUPP;
+}
+#endif
+
+#if IS_ENABLED(CONFIG_IMX_SM_CPU)
+int scmi_imx_cpu_started(struct udevice *dev, u32 cpuid, bool *started);
+int scmi_imx_cpu_reset_vector_set(struct udevice *dev, u32 cpuid, u32 flags, u64 vector,
+ bool start, bool boot, bool resume);
+int scmi_imx_cpu_start(struct udevice *dev, u32 cpuid, bool start);
+#else
+static inline int scmi_imx_cpu_started(struct udevice *dev, u32 cpuid, bool *started)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline int scmi_imx_cpu_reset_vector_set(struct udevice *dev, u32 cpuid, u32 flags,
+ u64 vector, bool start, bool boot, bool resume)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline int scmi_imx_cpu_start(struct udevice *dev, u32 cpuid, bool start)
+{
+ return -EOPNOTSUPP;
+}
+#endif
#endif
diff --git a/include/scmi_protocols.h b/include/scmi_protocols.h
index 95e0c3cce3b..bb74a57f79a 100644
--- a/include/scmi_protocols.h
+++ b/include/scmi_protocols.h
@@ -25,7 +25,8 @@ enum scmi_std_protocol {
SCMI_PROTOCOL_ID_RESET_DOMAIN = 0x16,
SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN = 0x17,
SCMI_PROTOCOL_ID_PINCTRL = 0x19,
- SCMI_PROTOCOL_ID_IMX_MISC = 0x84,
+ SCMI_PROTOCOL_ID_VENDOR_80 = 0x80,
+ SCMI_PROTOCOL_ID_VENDOR_82 = 0x82,
};
enum scmi_status_code {