From: Peng Fan <peng.fan@nxp.com>
Date: Fri, 28 Apr 2023 04:08:27 +0000 (+0800)
Subject: imx9: soc: support reset cause
X-Git-Tag: v2025.01-rc5-pxa1908~989^2~21
X-Git-Url: http://git.dujemihanovic.xyz/html/static/git-favicon.png?a=commitdiff_plain;h=5f2ecac54868dc0adb778f524a12c428009721ed;p=u-boot.git

imx9: soc: support reset cause

Support print reset cause. Since SRSR is not accessible from non-secure
world, so first save it to grp0, then read it in non-secure world.

Signed-off-by: Peng Fan <peng.fan@nxp.com>
---

diff --git a/arch/arm/mach-imx/imx9/soc.c b/arch/arm/mach-imx/imx9/soc.c
index a884e0863f..e476581e5e 100644
--- a/arch/arm/mach-imx/imx9/soc.c
+++ b/arch/arm/mach-imx/imx9/soc.c
@@ -19,6 +19,8 @@
 #include <asm/mach-imx/boot_mode.h>
 #include <asm/mach-imx/syscounter.h>
 #include <asm/armv8/mmu.h>
+#include <dm/device.h>
+#include <dm/device_compat.h>
 #include <dm/uclass.h>
 #include <env.h>
 #include <env_internal.h>
@@ -408,6 +410,18 @@ void get_board_serial(struct tag_serialnr *serialnr)
 }
 #endif
 
+static void save_reset_cause(void)
+{
+	struct src_general_regs *src = (struct src_general_regs *)SRC_GLOBAL_RBASE;
+	u32 srsr = readl(&src->srsr);
+
+	/* clear srsr in sec mode */
+	writel(srsr, &src->srsr);
+
+	/* Save value to GPR1 to pass to nonsecure */
+	writel(srsr, &src->gpr[0]);
+}
+
 int arch_cpu_init(void)
 {
 	if (IS_ENABLED(CONFIG_SPL_BUILD)) {
@@ -417,6 +431,9 @@ int arch_cpu_init(void)
 		clock_init();
 
 		trdc_early_init();
+
+		/* Save SRC SRSR to GPR1 and clear it */
+		save_reset_cause();
 	}
 
 	return 0;
@@ -650,3 +667,45 @@ int m33_prepare(void)
 
 	return 0;
 }
+
+int psci_sysreset_get_status(struct udevice *dev, char *buf, int size)
+{
+	static const char *reset_cause[] = {
+		"POR ",
+		"JTAG ",
+		"IPP USER ",
+		"WDOG1 ",
+		"WDOG2 ",
+		"WDOG3 ",
+		"WDOG4 ",
+		"WDOG5 ",
+		"TEMPSENSE ",
+		"CSU ",
+		"JTAG_SW ",
+		"M33_REQ ",
+		"M33_LOCKUP ",
+		"UNK ",
+		"UNK ",
+		"UNK "
+	};
+
+	struct src_general_regs *src = (struct src_general_regs *)SRC_GLOBAL_RBASE;
+	u32 srsr;
+	u32 i;
+	int res;
+
+	srsr = readl(&src->gpr[0]);
+
+	for (i = ARRAY_SIZE(reset_cause); i > 0; i--) {
+		if (srsr & (BIT(i - 1)))
+			break;
+	}
+
+	res = snprintf(buf, size, "Reset Status: %s\n", i ? reset_cause[i - 1] : "unknown reset");
+	if (res < 0) {
+		dev_err(dev, "Could not write reset status message (err = %d)\n", res);
+		return -EIO;
+	}
+
+	return 0;
+}