]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
firmware: arm_scmi: imx: Support getting reset reason of MISC protocol
authorPeng Fan <peng.fan@nxp.com>
Thu, 5 Mar 2026 01:56:44 +0000 (09:56 +0800)
committerSudeep Holla <sudeep.holla@kernel.org>
Tue, 5 May 2026 14:45:35 +0000 (15:45 +0100)
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>
Reviewed-by: Daniel Baluta <daniel.baluta@nxp.com>
Link: https://patch.msgid.link/20260305-scmi-imx-reset-v1-1-18de78978ba9@nxp.com
Signed-off-by: Sudeep Holla <sudeep.holla@kernel.org>
drivers/firmware/arm_scmi/vendors/imx/imx-sm-misc.c
include/linux/scmi_imx_protocol.h

index 0ada753367efe5cbcb8124ea46c05736c49f1ab8..637973fb45e6508c200211708358299cf7cbe3f1 100644 (file)
@@ -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)
index 2407d7693b6ba1303e07629e45e2a7eaaa906fd3..ab867463c08cc297e063aa1dc4189132a5ddb61a 100644 (file)
@@ -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 */