arm64: zynqmp: Show reset reason

Read reset reason reg and show it in log and also save it as variable.
Clearing reset reason when it is read to show only one status

Signed-off-by: Michal Simek <michal.simek@xilinx.com>
diff --git a/arch/arm/include/asm/arch-zynqmp/hardware.h b/arch/arm/include/asm/arch-zynqmp/hardware.h
index acc6825..f317250 100644
--- a/arch/arm/include/asm/arch-zynqmp/hardware.h
+++ b/arch/arm/include/asm/arch-zynqmp/hardware.h
@@ -30,6 +30,14 @@
 #define PS_MODE2	BIT(2)
 #define PS_MODE3	BIT(3)
 
+#define RESET_REASON_DEBUG_SYS	BIT(6)
+#define RESET_REASON_SOFT	BIT(5)
+#define RESET_REASON_SRST	BIT(4)
+#define RESET_REASON_PSONLY	BIT(3)
+#define RESET_REASON_PMU	BIT(2)
+#define RESET_REASON_INTERNAL	BIT(1)
+#define RESET_REASON_EXTERNAL	BIT(0)
+
 struct crlapb_regs {
 	u32 reserved0[36];
 	u32 cpu_r5_ctrl; /* 0x90 */
@@ -37,7 +45,9 @@
 	u32 timestamp_ref_ctrl; /* 0x128 */
 	u32 reserved2[53];
 	u32 boot_mode; /* 0x200 */
-	u32 reserved3[14];
+	u32 reserved3_0[7];
+	u32 reset_reason; /* 0x220 */
+	u32 reserved3_1[6];
 	u32 rst_lpd_top; /* 0x23C */
 	u32 reserved4[4];
 	u32 boot_pin_ctrl; /* 0x250 */
diff --git a/board/xilinx/zynqmp/zynqmp.c b/board/xilinx/zynqmp/zynqmp.c
index e41fec3..d3450ef 100644
--- a/board/xilinx/zynqmp/zynqmp.c
+++ b/board/xilinx/zynqmp/zynqmp.c
@@ -449,6 +449,47 @@
 {
 }
 
+static const struct {
+	u32 bit;
+	const char *name;
+} reset_reasons[] = {
+	{ RESET_REASON_DEBUG_SYS, "DEBUG" },
+	{ RESET_REASON_SOFT, "SOFT" },
+	{ RESET_REASON_SRST, "SRST" },
+	{ RESET_REASON_PSONLY, "PS-ONLY" },
+	{ RESET_REASON_PMU, "PMU" },
+	{ RESET_REASON_INTERNAL, "INTERNAL" },
+	{ RESET_REASON_EXTERNAL, "EXTERNAL" },
+	{}
+};
+
+static u32 reset_reason(void)
+{
+	u32 ret;
+	int i;
+	const char *reason = NULL;
+
+	ret = readl(&crlapb_base->reset_reason);
+
+	puts("Reset reason:\t");
+
+	for (i = 0; i < ARRAY_SIZE(reset_reasons); i++) {
+		if (ret & reset_reasons[i].bit) {
+			reason = reset_reasons[i].name;
+			printf("%s ", reset_reasons[i].name);
+			break;
+		}
+	}
+
+	puts("\n");
+
+	env_set("reset_reason", reason);
+
+	writel(~0, &crlapb_base->reset_reason);
+
+	return ret;
+}
+
 int board_late_init(void)
 {
 	u32 reg = 0;
@@ -540,6 +581,8 @@
 
 	env_set("boot_targets", new_targets);
 
+	reset_reason();
+
 	return 0;
 }