From: Peng Fan <[email protected]>

System Manager provides the last booted and shutdown reasons of the
logical machines (LM) and system using the SCMI misc protocol (Protocol
ID: 0x84, Message ID: 0xA). This path adds get_reset_reason() to query
and print these reasons in SPL and U-Boot.

Signed-off-by: Peng Fan <[email protected]>
Signed-off-by: Alice Guo <[email protected]>
Reviewed-by: Ye Li <[email protected]>
---
 arch/arm/include/asm/arch-imx9/sys_proto.h |   1 +
 arch/arm/mach-imx/imx9/scmi/soc.c          | 110 +++++++++++++++++++++++++++++
 board/freescale/imx95_evk/spl.c            |   3 +
 include/scmi_nxp_protocols.h               |  55 +++++++++++++++
 4 files changed, 169 insertions(+)

diff --git a/arch/arm/include/asm/arch-imx9/sys_proto.h 
b/arch/arm/include/asm/arch-imx9/sys_proto.h
index 455aa95339e..dead7a99a66 100644
--- a/arch/arm/include/asm/arch-imx9/sys_proto.h
+++ b/arch/arm/include/asm/arch-imx9/sys_proto.h
@@ -21,6 +21,7 @@ int m33_prepare(void);
 int low_drive_freq_update(void *blob);
 
 enum imx9_soc_voltage_mode soc_target_voltage_mode(void);
+int get_reset_reason(bool sys, bool lm);
 
 #define is_voltage_mode(mode) (soc_target_voltage_mode() == (mode))
 
diff --git a/arch/arm/mach-imx/imx9/scmi/soc.c 
b/arch/arm/mach-imx/imx9/scmi/soc.c
index f973652d0cb..f04b9255cdb 100644
--- a/arch/arm/mach-imx/imx9/scmi/soc.c
+++ b/arch/arm/mach-imx/imx9/scmi/soc.c
@@ -17,8 +17,10 @@
 #include <env_internal.h>
 #include <fuse.h>
 #include <imx_thermal.h>
+#include <linux/bitfield.h>
 #include <linux/iopoll.h>
 #include <scmi_agent.h>
+#include <scmi_nxp_protocols.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -468,6 +470,114 @@ err:
        printf("%s: fuse read err: %d\n", __func__, ret);
 }
 
+static char *rst_string[32] = {
+       "cm33_lockup",
+       "cm33_swreq",
+       "cm7_lockup",
+       "cm7_swreq",
+       "fccu",
+       "jtag_sw",
+       "ele",
+       "tempsense",
+       "wdog1",
+       "wdog2",
+       "wdog3",
+       "wdog4",
+       "wdog5",
+       "jtag",
+       "cm33_exc",
+       "bbm",
+       "sw",
+       "sm_err", "fusa_sreco", "pmic", "unused", "unused", "unused",
+       "unused", "unused", "unused", "unused", "unused", "unused",
+       "unused", "unused",
+       "por"
+};
+
+int get_reset_reason(bool sys, bool lm)
+{
+       struct scmi_imx_misc_reset_reason_in in = {
+               .flags = MISC_REASON_FLAG_SYSTEM,
+       };
+
+       struct scmi_imx_misc_reset_reason_out out = { 0 };
+       struct scmi_msg msg = {
+               .protocol_id = SCMI_PROTOCOL_ID_IMX_MISC,
+               .message_id = SCMI_IMX_MISC_RESET_REASON,
+               .in_msg = (u8 *)&in,
+               .in_msg_sz = sizeof(in),
+               .out_msg = (u8 *)&out,
+               .out_msg_sz = sizeof(out),
+       };
+       int ret;
+
+       struct udevice *dev;
+
+       ret = uclass_get_device_by_name(UCLASS_CLK, "protocol@14", &dev);
+       if (ret)
+               return ret;
+
+       if (sys) {
+               ret = devm_scmi_process_msg(dev, &msg);
+               if (out.status) {
+                       printf("%s:%d for SYS\n", __func__, out.status);
+                       return ret;
+               }
+
+               if (out.bootflags & MISC_BOOT_FLAG_VLD) {
+                       printf("SYS Boot reason: %s, origin: %ld, errid: %ld\n",
+                              rst_string[out.bootflags & 
MISC_BOOT_FLAG_REASON],
+                              out.bootflags & MISC_BOOT_FLAG_ORG_VLD ?
+                              FIELD_GET(MISC_BOOT_FLAG_ORIGIN, out.bootflags) 
: -1,
+                              out.bootflags & MISC_BOOT_FLAG_ERR_VLD ?
+                              FIELD_GET(MISC_BOOT_FLAG_ERR_ID, out.bootflags) 
: -1
+                              );
+               }
+               if (out.shutdownflags & MISC_SHUTDOWN_FLAG_VLD) {
+                       printf("SYS shutdown reason: %s, origin: %ld, errid: 
%ld\n",
+                              rst_string[out.bootflags & 
MISC_SHUTDOWN_FLAG_REASON],
+                              out.bootflags & MISC_SHUTDOWN_FLAG_ORG_VLD ?
+                              FIELD_GET(MISC_SHUTDOWN_FLAG_ORIGIN, 
out.bootflags) : -1,
+                              out.bootflags & MISC_SHUTDOWN_FLAG_ERR_VLD ?
+                              FIELD_GET(MISC_SHUTDOWN_FLAG_ERR_ID, 
out.bootflags) : -1
+                              );
+               }
+       }
+
+       if (lm) {
+               in.flags = 0;
+               memset(&out, 0, sizeof(struct scmi_imx_misc_reset_reason_out));
+
+               ret = devm_scmi_process_msg(dev, &msg);
+               if (out.status) {
+                       printf("%s:%d for LM\n", __func__, out.status);
+                       return ret;
+               }
+
+               if (out.bootflags & MISC_BOOT_FLAG_VLD) {
+                       printf("LM Boot reason: %s, origin: %ld, errid: %ld\n",
+                              rst_string[out.bootflags & 
MISC_BOOT_FLAG_REASON],
+                              out.bootflags & MISC_BOOT_FLAG_ORG_VLD ?
+                              FIELD_GET(MISC_BOOT_FLAG_ORIGIN, out.bootflags) 
: -1,
+                              out.bootflags & MISC_BOOT_FLAG_ERR_VLD ?
+                              FIELD_GET(MISC_BOOT_FLAG_ERR_ID, out.bootflags) 
: -1
+                              );
+               }
+
+               if (out.shutdownflags & MISC_SHUTDOWN_FLAG_VLD) {
+                       printf("LM shutdown reason: %s, origin: %ld, errid: 
%ld\n",
+                              rst_string[out.bootflags & 
MISC_SHUTDOWN_FLAG_REASON],
+                              out.bootflags & MISC_SHUTDOWN_FLAG_ORG_VLD ?
+                              FIELD_GET(MISC_SHUTDOWN_FLAG_ORIGIN, 
out.bootflags) : -1,
+                              out.bootflags & MISC_SHUTDOWN_FLAG_ERR_VLD ?
+                              FIELD_GET(MISC_SHUTDOWN_FLAG_ERR_ID, 
out.bootflags) : -1
+                              );
+               }
+       }
+
+       return 0;
+}
+
 const char *get_imx_type(u32 imxtype)
 {
        switch (imxtype) {
diff --git a/board/freescale/imx95_evk/spl.c b/board/freescale/imx95_evk/spl.c
index 08f4da0bb73..3d64097b4c7 100644
--- a/board/freescale/imx95_evk/spl.c
+++ b/board/freescale/imx95_evk/spl.c
@@ -5,6 +5,7 @@
 
 #include <asm/arch/clock.h>
 #include <asm/arch/mu.h>
+#include <asm/arch/sys_proto.h>
 #include <asm/mach-imx/boot_mode.h>
 #include <asm/sections.h>
 #include <hang.h>
@@ -65,5 +66,7 @@ void board_init_f(ulong dummy)
        debug("SOC: 0x%x\n", gd->arch.soc_rev);
        debug("LC: 0x%x\n", gd->arch.lifecycle);
 
+       get_reset_reason(true, false);
+
        board_init_r(NULL, 0);
 }
diff --git a/include/scmi_nxp_protocols.h b/include/scmi_nxp_protocols.h
new file mode 100644
index 00000000000..fe6ecd6a7cf
--- /dev/null
+++ b/include/scmi_nxp_protocols.h
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/*
+ * Copyright 2025 NXP
+ */
+
+#ifndef _SCMI_NXP_PROTOCOLS_H
+#define _SCMI_NXP_PROTOCOLS_H
+
+#include <asm/types.h>
+#include <linux/bitops.h>
+
+enum scmi_imx_protocol {
+       SCMI_IMX_PROTOCOL_ID_MISC = 0x84,
+};
+
+#define SCMI_PAYLOAD_LEN       100
+
+#define SCMI_ARRAY(X, Y)       ((SCMI_PAYLOAD_LEN - (X)) / sizeof(Y))
+
+#define SCMI_IMX_MISC_RESET_REASON     0xA
+
+struct scmi_imx_misc_reset_reason_in {
+#define MISC_REASON_FLAG_SYSTEM                BIT(0)
+       u32 flags;
+};
+
+struct scmi_imx_misc_reset_reason_out {
+       s32 status;
+       /* 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)
+       u32 bootflags;
+       /* 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)
+       u32 shutdownflags;
+       /* Array of extended info words */
+#define MISC_MAX_EXTINFO       SCMI_ARRAY(16, u32)
+       u32 extInfo[MISC_MAX_EXTINFO];
+};
+
+#endif

-- 
2.43.0

Reply via email to