]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
imx95: Add get_reset_reason() to retrieve the LM/system last booted/shutdown reasons
authorPeng Fan <peng.fan@nxp.com>
Tue, 23 Sep 2025 02:14:55 +0000 (10:14 +0800)
committerFabio Estevam <festevam@gmail.com>
Fri, 26 Sep 2025 12:51:21 +0000 (09:51 -0300)
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 <peng.fan@nxp.com>
Signed-off-by: Alice Guo <alice.guo@nxp.com>
Reviewed-by: Ye Li <ye.li@nxp.com>
arch/arm/include/asm/arch-imx9/sys_proto.h
arch/arm/mach-imx/imx9/scmi/soc.c
board/freescale/imx95_evk/spl.c
include/scmi_nxp_protocols.h [new file with mode: 0644]

index 455aa95339e90a621afbb5386c5945ef16ab3495..dead7a99a6645989b435d2c8e678ef10d18c4e18 100644 (file)
@@ -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))
 
index f973652d0cbe8723b0cdc1a6235fbdd719146065..f04b9255cdb52b4ef8fcca4d4cb1cc219e6d78bd 100644 (file)
 #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) {
index 08f4da0bb738ff8f3ab5c726dc41dbd85da1a508..3d64097b4c7574778ef31b43f03963ec203a4b2a 100644 (file)
@@ -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 (file)
index 0000000..fe6ecd6
--- /dev/null
@@ -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