]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
firmware: arm_scmi: imx: Support getting syslog of MISC protocol
authorPeng Fan <peng.fan@nxp.com>
Wed, 29 Oct 2025 12:07:01 +0000 (20:07 +0800)
committerShawn Guo <shawnguo@kernel.org>
Sat, 17 Jan 2026 02:32:21 +0000 (10:32 +0800)
MISC protocol supports getting system log regarding system sleep latency,
wakeup interrupt and etc. Add the API for user to retrieve the information
from SM.

Signed-off-by: Peng Fan <peng.fan@nxp.com>
Acked-by: Sudeep Holla <sudeep.holla@arm.com>
Signed-off-by: Shawn Guo <shawnguo@kernel.org>
drivers/firmware/arm_scmi/vendors/imx/imx-sm-misc.c
include/linux/scmi_imx_protocol.h

index 700a3f24f4efc153ca4a9ef1a9e50a7ece492a18..eae0b0562f6cf1931be612852ba2651f60820e6d 100644 (file)
@@ -28,6 +28,7 @@ enum scmi_imx_misc_protocol_cmd {
        SCMI_IMX_MISC_DISCOVER_BUILD_INFO = 0x6,
        SCMI_IMX_MISC_CTRL_NOTIFY = 0x8,
        SCMI_IMX_MISC_CFG_INFO_GET = 0xC,
+       SCMI_IMX_MISC_SYSLOG_GET = 0xD,
        SCMI_IMX_MISC_BOARD_INFO = 0xE,
 };
 
@@ -89,6 +90,19 @@ struct scmi_imx_misc_cfg_info_out {
        u8 cfgname[MISC_MAX_CFGNAME];
 };
 
+struct scmi_imx_misc_syslog_in {
+       __le32 flags;
+       __le32 index;
+};
+
+#define REMAINING(x)   le32_get_bits((x), GENMASK(31, 20))
+#define RETURNED(x)    le32_get_bits((x), GENMASK(11, 0))
+
+struct scmi_imx_misc_syslog_out {
+       __le32 numlogflags;
+       __le32 syslog[];
+};
+
 static int scmi_imx_misc_attributes_get(const struct scmi_protocol_handle *ph,
                                        struct scmi_imx_misc_info *mi)
 {
@@ -371,10 +385,79 @@ static int scmi_imx_misc_cfg_info_get(const struct scmi_protocol_handle *ph)
        return ret;
 }
 
+struct scmi_imx_misc_syslog_ipriv {
+       u32 *array;
+       u16 *size;
+};
+
+static void iter_misc_syslog_prepare_message(void *message, u32 desc_index,
+                                            const void *priv)
+{
+       struct scmi_imx_misc_syslog_in *msg = message;
+
+       msg->flags = cpu_to_le32(0);
+       msg->index = cpu_to_le32(desc_index);
+}
+
+static int iter_misc_syslog_update_state(struct scmi_iterator_state *st,
+                                        const void *response, void *priv)
+{
+       const struct scmi_imx_misc_syslog_out *r = response;
+       struct scmi_imx_misc_syslog_ipriv *p = priv;
+
+       st->num_returned = RETURNED(r->numlogflags);
+       st->num_remaining = REMAINING(r->numlogflags);
+       *p->size = st->num_returned + st->num_remaining;
+
+       return 0;
+}
+
+static int
+iter_misc_syslog_process_response(const struct scmi_protocol_handle *ph,
+                                 const void *response,
+                                 struct scmi_iterator_state *st, void *priv)
+{
+       const struct scmi_imx_misc_syslog_out *r = response;
+       struct scmi_imx_misc_syslog_ipriv *p = priv;
+
+       p->array[st->desc_index + st->loop_idx] =
+               le32_to_cpu(r->syslog[st->loop_idx]);
+
+       return 0;
+}
+
+static int scmi_imx_misc_syslog_get(const struct scmi_protocol_handle *ph, u16 *size,
+                                   void *array)
+{
+       struct scmi_iterator_ops ops = {
+               .prepare_message = iter_misc_syslog_prepare_message,
+               .update_state = iter_misc_syslog_update_state,
+               .process_response = iter_misc_syslog_process_response,
+       };
+       struct scmi_imx_misc_syslog_ipriv ipriv = {
+               .array = array,
+               .size = size,
+       };
+       void *iter;
+
+       if (!array || !size || !*size)
+               return -EINVAL;
+
+       iter = ph->hops->iter_response_init(ph, &ops, *size, SCMI_IMX_MISC_SYSLOG_GET,
+                                           sizeof(struct scmi_imx_misc_syslog_in),
+                                           &ipriv);
+       if (IS_ERR(iter))
+               return PTR_ERR(iter);
+
+       /* If firmware return NOT SUPPORTED, propagate value to caller */
+       return ph->hops->iter_response_run(iter);
+}
+
 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,
 };
 
 static int scmi_imx_misc_protocol_init(const struct scmi_protocol_handle *ph)
index 27bd372cbfb142b6acb0b1cf4b82f061529d0d45..2407d7693b6ba1303e07629e45e2a7eaaa906fd3 100644 (file)
@@ -59,6 +59,8 @@ struct scmi_imx_misc_proto_ops {
                             u32 *num, u32 *val);
        int (*misc_ctrl_req_notify)(const struct scmi_protocol_handle *ph,
                                    u32 ctrl_id, u32 evt_id, u32 flags);
+       int (*misc_syslog)(const struct scmi_protocol_handle *ph, u16 *size,
+                          void *array);
 };
 
 /* See LMM_ATTRIBUTES in imx95.rst */