blob: 0381b5d8473226f190c22938272eff7a3404d947 [file] [log] [blame]
Thang Q. Nguyen44cf8fd2020-12-22 04:27:36 +00001From af4353ab19aaf29dc68ff89a0d581102ca5be43c Mon Sep 17 00:00:00 2001
2From: "Thang Q. Nguyen" <thang@os.amperecomputing.com>
3Date: Wed, 6 Jan 2021 06:33:36 +0000
4Subject: [PATCH] aspeed: support passing system reset status to kernel via
5 bootargs
6
7This is a backport of the patch file from
8openbmc/meta-yadro/meta-nicole/recipes-bsp/u-boot/
9to add the Aspeed reset reason to bootargs so kernel applications
10can query it.
11
12Test case: /proc/cmdline must contain:
13 - resetreason=power after cold bmc boot
14 - resetreason=watchdog after warm bmc reboot
15
16Signed-off-by: Chanh Nguyen <chanh@os.amperecomputing.com>
17Signed-off-by: Thang Q. Nguyen <thang@os.amperecomputing.com>
18---
19 arch/arm/include/asm/arch-aspeed/ast_scu.h | 2 +-
20 arch/arm/mach-aspeed/ast-scu.c | 6 +-
21 board/aspeed/ast-g5/ast-g5.c | 81 ++++++++++++++++++++++
22 3 files changed, 87 insertions(+), 2 deletions(-)
23
24diff --git a/arch/arm/include/asm/arch-aspeed/ast_scu.h b/arch/arm/include/asm/arch-aspeed/ast_scu.h
25index d2c010a0dc..f5c9126ec0 100644
26--- a/arch/arm/include/asm/arch-aspeed/ast_scu.h
27+++ b/arch/arm/include/asm/arch-aspeed/ast_scu.h
28@@ -29,7 +29,7 @@
29 #define __AST_SCU_H
30
31 extern void ast_scu_show_system_info (void);
32-extern void ast_scu_sys_rest_info(void);
33+extern u32 ast_scu_sys_rest_info(void);
34 extern void ast_scu_security_info(void);
35 extern u32 ast_scu_revision_id(void);
36 extern u32 ast_scu_get_vga_memsize(void);
37diff --git a/arch/arm/mach-aspeed/ast-scu.c b/arch/arm/mach-aspeed/ast-scu.c
38index ef90ef3805..c7ab66415f 100644
39--- a/arch/arm/mach-aspeed/ast-scu.c
40+++ b/arch/arm/mach-aspeed/ast-scu.c
41@@ -494,22 +494,26 @@ void ast_scu_security_info(void)
42 }
43 }
44
45-void ast_scu_sys_rest_info(void)
46+u32 ast_scu_sys_rest_info(void)
47 {
48 u32 rest = ast_scu_read(AST_SCU_SYS_CTRL);
49
50 if (rest & SCU_SYS_EXT_RESET_FLAG) {
51 printf("RST : External\n");
52 ast_scu_write(SCU_SYS_EXT_RESET_FLAG, AST_SCU_SYS_CTRL);
53+ rest = SCU_SYS_EXT_RESET_FLAG;
54 } else if (rest & SCU_SYS_WDT_RESET_FLAG) {
55 printf("RST : Watchdog\n");
56 ast_scu_write(SCU_SYS_WDT_RESET_FLAG, AST_SCU_SYS_CTRL);
57+ rest = SCU_SYS_WDT_RESET_FLAG;
58 } else if (rest & SCU_SYS_PWR_RESET_FLAG) {
59 printf("RST : Power On\n");
60 ast_scu_write(SCU_SYS_PWR_RESET_FLAG, AST_SCU_SYS_CTRL);
61+ rest = SCU_SYS_PWR_RESET_FLAG;
62 } else {
63 printf("RST : CLK en\n");
64 }
65+ return rest;
66 }
67
68 u32 ast_scu_get_vga_memsize(void)
69diff --git a/board/aspeed/ast-g5/ast-g5.c b/board/aspeed/ast-g5/ast-g5.c
70index 9bf6c905fe..9e27bce0f5 100644
71--- a/board/aspeed/ast-g5/ast-g5.c
72+++ b/board/aspeed/ast-g5/ast-g5.c
73@@ -8,6 +8,8 @@
74 */
75
76 #include <common.h>
77+#include <stdlib.h>
78+#include <asm/arch/regs-scu.h>
79 #include <netdev.h>
80
81 #include <asm/arch/ast_scu.h>
82@@ -25,9 +27,76 @@ int board_init(void)
83 }
84
85 #ifdef CONFIG_BOARD_LATE_INIT
86+static void update_bootargs_cmd(const char *key, const char *value)
87+{
88+ int buf_len;
89+ char *buf;
90+ char *cmdline;
91+ char *end = NULL;
92+
93+ if (!key || (key[0] == '\0')) {
94+ printf("%s: Empty key not allowed\n", __func__);
95+ return;
96+ }
97+
98+ cmdline = getenv("bootargs");
99+
100+ /* Allocate space for maximum possible new command line */
101+ buf_len = (cmdline ? strlen(cmdline) : 0)
102+ + 1 /* spacebar as delimiter */
103+ + strlen(key)
104+ + (value ? 1 /* equal sign */ + strlen(value) : 0)
105+ + 1 /* terminating null */;
106+
107+ buf = calloc(buf_len, sizeof(char));
108+ if (!buf) {
109+ printf("%s: out of memory\n", __func__);
110+ return;
111+ }
112+
113+ if (cmdline)
114+ {
115+ char *start = strstr(cmdline, key);
116+
117+ /* Check for full word match. Match should be start of cmdline
118+ * or there should be space before match
119+ **/
120+ if (start && ((start == cmdline) || (*(start - 1) == ' '))) {
121+ strncat(buf, cmdline, (start - cmdline));
122+
123+ /* Find the end of the keyword[=value] pair,
124+ * including a single training space character, if any.
125+ * Skip the found substring, mark the tail of cmdline.
126+ **/
127+ end = strchr(start, ' ');
128+ if (end) {
129+ end++;
130+ }
131+ } else {
132+ strcat(buf, cmdline);
133+ strcat(buf, " ");
134+ }
135+ }
136+
137+ strcat(buf, key);
138+ if (value) {
139+ strcat(buf, "=");
140+ strcat(buf, value);
141+ }
142+
143+ if (end) {
144+ strcat(buf, " ");
145+ strcat(buf, end);
146+ }
147+
148+ setenv("bootargs", buf);
149+ free(buf);
150+}
151+
152 int board_late_init(void)
153 {
154 u32 val;
155+ u32 reset_reason = ast_scu_sys_rest_info();
156
157 /* Switch PWM to GPIO mode to make FAN run in max speed */
158 ast_scu_switch_pwm_to_gpio_mode();
159@@ -44,6 +113,18 @@ int board_late_init(void)
160 writel(0xaa, AST_SCU_BASE);
161 #endif
162
163+ if (reset_reason & SCU_SYS_EXT_RESET_FLAG) {
164+ update_bootargs_cmd("resetreason", "external");
165+ } else if (reset_reason & SCU_SYS_WDT_RESET_FLAG) {
166+ update_bootargs_cmd("resetreason", "watchdog");
167+ } else if (reset_reason & SCU_SYS_PWR_RESET_FLAG) {
168+ update_bootargs_cmd("resetreason", "power");
169+ } else {
170+ char value[32];
171+ snprintf(value, sizeof(value) - 1, "0x%x", reset_reason);
172+ update_bootargs_cmd("resetreason", value);
173+ }
174+
175 return 0;
176 }
177 #endif
178--
1792.25.1
180