[PATCH 1/2] firmware: arm_scmi: imx: Support getting reset reason of MISC protocol
From: Peng Fan (OSS) <hidden>
Date: 2026-03-05 01:55:31
Also in:
arm-scmi, imx, linux-arm-kernel
Subsystem:
system control & power/management interface (scpi/scmi) message protocol drivers, system control management interface (scmi) i.mx extension message protocol drivers, the rest · Maintainers:
Sudeep Holla, Peng Fan, Linus Torvalds
From: Peng Fan <peng.fan@nxp.com> MISC protocol supports getting reset reason per Logical Machine or System. Add the API for user to retrieve the information from System Manager. Signed-off-by: Peng Fan <peng.fan@nxp.com> --- .../firmware/arm_scmi/vendors/imx/imx-sm-misc.c | 86 ++++++++++++++++++++++ include/linux/scmi_imx_protocol.h | 14 ++++ 2 files changed, 100 insertions(+)
diff --git a/drivers/firmware/arm_scmi/vendors/imx/imx-sm-misc.c b/drivers/firmware/arm_scmi/vendors/imx/imx-sm-misc.c
index 0ada753367efe5cbcb8124ea46c05736c49f1ab8..637973fb45e6508c200211708358299cf7cbe3f1 100644
--- a/drivers/firmware/arm_scmi/vendors/imx/imx-sm-misc.c
+++ b/drivers/firmware/arm_scmi/vendors/imx/imx-sm-misc.c@@ -27,6 +27,7 @@ enum scmi_imx_misc_protocol_cmd { SCMI_IMX_MISC_CTRL_GET = 0x4, SCMI_IMX_MISC_DISCOVER_BUILD_INFO = 0x6, SCMI_IMX_MISC_CTRL_NOTIFY = 0x8, + SCMI_IMX_MISC_RESET_REASON_GET = 0xA, SCMI_IMX_MISC_CFG_INFO_GET = 0xC, SCMI_IMX_MISC_SYSLOG_GET = 0xD, SCMI_IMX_MISC_BOARD_INFO = 0xE,
@@ -89,6 +90,37 @@ struct scmi_imx_misc_cfg_info_out { u8 cfgname[MISC_MAX_CFGNAME]; }; +struct scmi_imx_misc_reset_reason_in { +#define MISC_REASON_FLAG_SYSTEM BIT(0) + __le32 flags; +}; + +struct scmi_imx_misc_reset_reason_out { + /* Boot reason flags */ +#define MISC_BOOT_FLAG_VLD BIT(31) +#define MISC_BOOT_FLAG_ORG_VLD BIT(28) +#define MISC_BOOT_FLAG_ORIGIN GENMASK(27, 24) +#define MISC_BOOT_FLAG_O_SHIFT 24 +#define MISC_BOOT_FLAG_ERR_VLD BIT(23) +#define MISC_BOOT_FLAG_ERR_ID GENMASK(22, 8) +#define MISC_BOOT_FLAG_E_SHIFT 8 +#define MISC_BOOT_FLAG_REASON GENMASK(7, 0) + __le32 b_flags; + /* Shutdown reason flags */ +#define MISC_SHUTDOWN_FLAG_VLD BIT(31) +#define MISC_SHUTDOWN_FLAG_EXT_LEN GENMASK(30, 29) +#define MISC_SHUTDOWN_FLAG_ORG_VLD BIT(28) +#define MISC_SHUTDOWN_FLAG_ORIGIN GENMASK(27, 24) +#define MISC_SHUTDOWN_FLAG_O_SHIFT 24 +#define MISC_SHUTDOWN_FLAG_ERR_VLD BIT(23) +#define MISC_SHUTDOWN_FLAG_ERR_ID GENMASK(22, 8) +#define MISC_SHUTDOWN_FLAG_E_SHIFT 8 +#define MISC_SHUTDOWN_FLAG_REASON GENMASK(7, 0) + __le32 s_flags; + /* Array of extended info words */ + __le32 extinfo[MISC_EXT_INFO_LEN_MAX]; +}; + struct scmi_imx_misc_syslog_in { __le32 flags; __le32 index;
@@ -452,11 +484,65 @@ static int scmi_imx_misc_syslog_get(const struct scmi_protocol_handle *ph, u16 * return ph->hops->iter_response_run(iter); } +static int scmi_imx_misc_reset_reason(const struct scmi_protocol_handle *ph, bool system, + struct scmi_imx_misc_reset_reason *boot_r, + struct scmi_imx_misc_reset_reason *shut_r, + u32 *extinfo) +{ + struct scmi_imx_misc_reset_reason_in *in; + struct scmi_imx_misc_reset_reason_out *out; + struct scmi_xfer *t; + int ret; + + ret = ph->xops->xfer_get_init(ph, SCMI_IMX_MISC_RESET_REASON_GET, sizeof(*in), + sizeof(*out), &t); + if (ret) + return ret; + + in = t->tx.buf; + if (system) + in->flags = le32_encode_bits(1, MISC_REASON_FLAG_SYSTEM); + else + in->flags = cpu_to_le32(0); + + ret = ph->xops->do_xfer(ph, t); + if (!ret) { + out = t->rx.buf; + if (boot_r) { + boot_r->valid = le32_get_bits(out->b_flags, MISC_BOOT_FLAG_VLD); + boot_r->orig_valid = le32_get_bits(out->b_flags, MISC_BOOT_FLAG_ORG_VLD); + boot_r->err_valid = le32_get_bits(out->b_flags, MISC_BOOT_FLAG_ERR_VLD); + boot_r->reason = le32_get_bits(out->b_flags, MISC_BOOT_FLAG_REASON); + boot_r->origin = le32_get_bits(out->b_flags, MISC_BOOT_FLAG_ORIGIN); + boot_r->errid = le32_get_bits(out->b_flags, MISC_BOOT_FLAG_ERR_ID); + } + + if (shut_r) { + shut_r->valid = le32_get_bits(out->s_flags, MISC_SHUTDOWN_FLAG_VLD); + shut_r->orig_valid = le32_get_bits(out->s_flags, + MISC_SHUTDOWN_FLAG_ORG_VLD); + shut_r->err_valid = le32_get_bits(out->s_flags, + MISC_SHUTDOWN_FLAG_ERR_VLD); + shut_r->reason = le32_get_bits(out->s_flags, MISC_SHUTDOWN_FLAG_REASON); + shut_r->origin = le32_get_bits(out->s_flags, MISC_SHUTDOWN_FLAG_ORIGIN); + shut_r->errid = le32_get_bits(out->s_flags, MISC_SHUTDOWN_FLAG_ERR_ID); + } + + if (extinfo) + memcpy_from_le32(extinfo, out->extinfo, MISC_EXT_INFO_LEN_MAX); + } + + ph->xops->xfer_put(ph, t); + + return ret; +} + static const struct scmi_imx_misc_proto_ops scmi_imx_misc_proto_ops = { .misc_ctrl_set = scmi_imx_misc_ctrl_set, .misc_ctrl_get = scmi_imx_misc_ctrl_get, .misc_ctrl_req_notify = scmi_imx_misc_ctrl_notify, .misc_syslog = scmi_imx_misc_syslog_get, + .misc_reset_reason = scmi_imx_misc_reset_reason, }; static int scmi_imx_misc_protocol_init(const struct scmi_protocol_handle *ph)
diff --git a/include/linux/scmi_imx_protocol.h b/include/linux/scmi_imx_protocol.h
index 2407d7693b6ba1303e07629e45e2a7eaaa906fd3..ab867463c08cc297e063aa1dc4189132a5ddb61a 100644
--- a/include/linux/scmi_imx_protocol.h
+++ b/include/linux/scmi_imx_protocol.h@@ -52,6 +52,17 @@ struct scmi_imx_misc_ctrl_notify_report { unsigned int flags; }; + +#define MISC_EXT_INFO_LEN_MAX 4 +struct scmi_imx_misc_reset_reason { + bool valid:1; + bool orig_valid:1; + bool err_valid:1; + u32 reason; + u32 origin; + u32 errid; +}; + struct scmi_imx_misc_proto_ops { int (*misc_ctrl_set)(const struct scmi_protocol_handle *ph, u32 id, u32 num, u32 *val);
@@ -61,6 +72,9 @@ struct scmi_imx_misc_proto_ops { u32 ctrl_id, u32 evt_id, u32 flags); int (*misc_syslog)(const struct scmi_protocol_handle *ph, u16 *size, void *array); + int (*misc_reset_reason)(const struct scmi_protocol_handle *ph, + bool system, struct scmi_imx_misc_reset_reason *boot_r, + struct scmi_imx_misc_reset_reason *shut_r, u32 *extinfo); }; /* See LMM_ATTRIBUTES in imx95.rst */
--
2.37.1