summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0023-Add-WDT-to-u-boot-to-cover-booting-failures.patch
blob: e6240341316e25c0607558f030697e0a39fb8028 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
From 385629a99a8d07182812264f2868d5f85fb711e0 Mon Sep 17 00:00:00 2001
From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
Date: Wed, 16 Sep 2020 13:25:36 -0700
Subject: [PATCH] Add WDT to u-boot to cover booting failures

This commit enables WDT1 in early u-boot and before loading kernel
image to make BMC reset to cover booting failures. If BMC meets any
failure or if kernel can't initiate watchdog timer properly, BMC will
be reset by this watchdog.

Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
---
 arch/arm/mach-aspeed/ast2600/platform.S | 15 +++++
 board/aspeed/ast2600_intel/intel.c      | 50 ++++++++++++++--
 common/board_f.c                        |  1 +
 common/image.c                          |  3 +-
 drivers/mtd/spi/spi-nor-core.c          |  5 ++
 drivers/watchdog/ast_wdt.c              | 78 ++++++++++++++-----------
 include/configs/aspeed-common.h         |  2 +
 7 files changed, 116 insertions(+), 38 deletions(-)

diff --git a/arch/arm/mach-aspeed/ast2600/platform.S b/arch/arm/mach-aspeed/ast2600/platform.S
index 027265593f03..e57bd325277f 100644
--- a/arch/arm/mach-aspeed/ast2600/platform.S
+++ b/arch/arm/mach-aspeed/ast2600/platform.S
@@ -64,6 +64,9 @@
 #define AST_MAC2_CTRL2		(AST_MAC2_BASE + 0x058)
 
 #define AST_WDT1_BASE		0x1E785000
+#define AST_WDT1_RELOAD_VAL	(AST_WDT1_BASE + 0x004)
+#define AST_WDT1_RESTART_CTRL	(AST_WDT1_BASE + 0x008)
+#define AST_WDT1_CTRL		(AST_WDT1_BASE + 0x00C)
 #define AST_WDT1_RESET_MASK1	(AST_WDT1_BASE + 0x01C)
 #define AST_WDT1_RESET_MASK2	(AST_WDT1_BASE + 0x020)
 
@@ -328,6 +331,18 @@ wait_lock:
 	ldr	r1, =AST_SCU_CA7_PARITY_CHK
 	str	r0, [r1]
 
+#ifdef CONFIG_HW_WATCHDOG
+	/* Enable WDT1 to recover u-boot hang */
+	ldr   r0, =AST_WDT1_RELOAD_VAL
+	ldr   r1, =0x00500000             @ ~5 seconds
+	str   r1, [r0]
+	ldr   r0, =AST_WDT1_RESTART_CTRL
+	ldr   r1, =0x00004755
+	str   r1, [r0]
+	ldr   r0, =AST_WDT1_CTRL
+	ldr   r1, =0x00000013
+	str   r1, [r0]
+#endif
 #if 0
 	ldr	r1, =AST_FMC_WDT2_CTRL_MODE
 	str	r0, [r1]
diff --git a/board/aspeed/ast2600_intel/intel.c b/board/aspeed/ast2600_intel/intel.c
index 948f8a01f868..1a95893631c8 100644
--- a/board/aspeed/ast2600_intel/intel.c
+++ b/board/aspeed/ast2600_intel/intel.c
@@ -7,6 +7,7 @@
 #include <asm/io.h>
 #include <led.h>
 #include <malloc.h>
+#include <wdt.h>
 
 #define SYS_PWR_RESET_FLAG	BIT(0) /* from scu_info.c */
 #define WATCHDOG_RESET_BIT	BIT(20)
@@ -584,13 +585,54 @@ void board_preboot_os(void)
 		led_set_state(dev, LEDST_ON);
 }
 
-#ifdef CONFIG_WATCHDOG
-/* watchdog stuff */
-void watchdog_init(void)
+#ifdef CONFIG_HW_WATCHDOG
+#define WDT_TIMEOUT_DEFAULT	0x6000000 /* ~100 seconds */
+
+void hw_watchdog_init(void)
+{
+	struct udevice *dev;
+	int ret;
+
+	ret = uclass_first_device(UCLASS_WDT, &dev);
+	if (ret) {
+		debug("Can't find a WDT: %d\n", ret);
+		return;
+	}
+
+	ret = wdt_start(dev, WDT_TIMEOUT_DEFAULT, 0);
+	if (ret)
+		debug("WDT start failed: %d\n", ret);
+}
+
+void hw_watchdog_reset(void)
 {
+	struct udevice *dev;
+	int ret;
+
+	ret = uclass_first_device(UCLASS_WDT, &dev);
+	if (ret) {
+		debug("Can't find a WDT: %d\n", ret);
+		return;
+	}
+
+	ret = wdt_reset(dev);
+	if (ret)
+		debug("WDT reset failed: %d\n", ret);
 }
 
-void watchdog_reset(void)
+void hw_watchdog_disable(void)
 {
+	struct udevice *dev;
+	int ret;
+
+	ret = uclass_first_device(UCLASS_WDT, &dev);
+	if (ret) {
+		debug("Can't find a WDT: %d\n", ret);
+		return;
+	}
+
+	ret = wdt_stop(dev);
+	if (ret)
+		debug("WDT stop failed: %d\n", ret);
 }
 #endif
diff --git a/common/board_f.c b/common/board_f.c
index 149a7229e8fa..fe3e8e59d93e 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -94,6 +94,7 @@ static int init_func_watchdog_init(void)
 {
 # if defined(CONFIG_HW_WATCHDOG) && \
 	(defined(CONFIG_M68K) || defined(CONFIG_MICROBLAZE) || \
+	defined(CONFIG_ASPEED_AST2600) || \
 	defined(CONFIG_SH) || \
 	defined(CONFIG_DESIGNWARE_WATCHDOG) || \
 	defined(CONFIG_IMX_WATCHDOG))
diff --git a/common/image.c b/common/image.c
index 4d4248f234fb..90687092e1ae 100644
--- a/common/image.c
+++ b/common/image.c
@@ -528,7 +528,8 @@ void memmove_wd(void *to, void *from, size_t len, ulong chunksz)
 	if (to == from)
 		return;
 
-#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
+#if !defined(CONFIG_ASPEED_SPI_DMA) && \
+    (defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG))
 	if (to > from) {
 		from += len;
 		to += len;
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
index a8f5b6158241..69dfc7f21698 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -20,6 +20,7 @@
 #include <linux/mtd/spi-nor.h>
 #include <spi-mem.h>
 #include <spi.h>
+#include <watchdog.h>
 
 #include "sf_internal.h"
 
@@ -429,6 +430,10 @@ static int spi_nor_wait_till_ready_with_timeout(struct spi_nor *nor,
 	unsigned long timebase;
 	int ret;
 
+#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
+	WATCHDOG_RESET();
+#endif
+
 	timebase = get_timer(0);
 
 	while (get_timer(timebase) < timeout) {
diff --git a/drivers/watchdog/ast_wdt.c b/drivers/watchdog/ast_wdt.c
index c2dc3cf548d2..811ead41bb95 100644
--- a/drivers/watchdog/ast_wdt.c
+++ b/drivers/watchdog/ast_wdt.c
@@ -19,10 +19,11 @@
 #define WDT_CTRL_RESET_MODE_SHIFT	5
 #define WDT_CTRL_RESET_MODE_MASK	3
 
-#define WDT_CTRL_EN			(1 << 0)
-#define WDT_CTRL_RESET			(1 << 1)
-#define WDT_CTRL_CLK1MHZ		(1 << 4)
-#define WDT_CTRL_2ND_BOOT		(1 << 7)
+#define WDT_CTRL_EN			BIT(0)
+#define WDT_CTRL_RESET			BIT(1)
+#define WDT_CTRL_CLK1MHZ		BIT(4) /* AST2400/2500 */
+#define WDT_CTRL_WDT_RST_BY_SOC_RST	BIT(4) /* AST2600 */
+#define WDT_CTRL_2ND_BOOT		BIT(7)
 
 /* Values for Reset Mode */
 #define WDT_CTRL_RESET_SOC		0
@@ -31,32 +32,32 @@
 #define WDT_CTRL_RESET_MASK		3
 
 /* Reset Mask register */
-#define WDT_RESET_ARM			(1 << 0)
-#define WDT_RESET_COPROC		(1 << 1)
-#define WDT_RESET_SDRAM			(1 << 2)
-#define WDT_RESET_AHB			(1 << 3)
-#define WDT_RESET_I2C			(1 << 4)
-#define WDT_RESET_MAC1			(1 << 5)
-#define WDT_RESET_MAC2			(1 << 6)
-#define WDT_RESET_GCRT			(1 << 7)
-#define WDT_RESET_USB20			(1 << 8)
-#define WDT_RESET_USB11_HOST		(1 << 9)
-#define WDT_RESET_USB11_EHCI2		(1 << 10)
-#define WDT_RESET_VIDEO			(1 << 11)
-#define WDT_RESET_HAC			(1 << 12)
-#define WDT_RESET_LPC			(1 << 13)
-#define WDT_RESET_SDSDIO		(1 << 14)
-#define WDT_RESET_MIC			(1 << 15)
-#define WDT_RESET_CRT2C			(1 << 16)
-#define WDT_RESET_PWM			(1 << 17)
-#define WDT_RESET_PECI			(1 << 18)
-#define WDT_RESET_JTAG			(1 << 19)
-#define WDT_RESET_ADC			(1 << 20)
-#define WDT_RESET_GPIO			(1 << 21)
-#define WDT_RESET_MCTP			(1 << 22)
-#define WDT_RESET_XDMA			(1 << 23)
-#define WDT_RESET_SPI			(1 << 24)
-#define WDT_RESET_MISC			(1 << 25)
+#define WDT_RESET_ARM			BIT(0)
+#define WDT_RESET_COPROC		BIT(1)
+#define WDT_RESET_SDRAM			BIT(2)
+#define WDT_RESET_AHB			BIT(3)
+#define WDT_RESET_I2C			BIT(4)
+#define WDT_RESET_MAC1			BIT(5)
+#define WDT_RESET_MAC2			BIT(6)
+#define WDT_RESET_GCRT			BIT(7)
+#define WDT_RESET_USB20			BIT(8)
+#define WDT_RESET_USB11_HOST		BIT(9)
+#define WDT_RESET_USB11_EHCI2		BIT(10)
+#define WDT_RESET_VIDEO			BIT(11)
+#define WDT_RESET_HAC			BIT(12)
+#define WDT_RESET_LPC			BIT(13)
+#define WDT_RESET_SDSDIO		BIT(14)
+#define WDT_RESET_MIC			BIT(15)
+#define WDT_RESET_CRT2C			BIT(16)
+#define WDT_RESET_PWM			BIT(17)
+#define WDT_RESET_PECI			BIT(18)
+#define WDT_RESET_JTAG			BIT(19)
+#define WDT_RESET_ADC			BIT(20)
+#define WDT_RESET_GPIO			BIT(21)
+#define WDT_RESET_MCTP			BIT(22)
+#define WDT_RESET_XDMA			BIT(23)
+#define WDT_RESET_SPI			BIT(24)
+#define WDT_RESET_MISC			BIT(25)
 
 #define WDT_RESET_DEFAULT						\
 	(WDT_RESET_ARM | WDT_RESET_COPROC | WDT_RESET_I2C |		\
@@ -98,12 +99,18 @@ struct ast_wdt_priv {
 static int ast_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
 {
 	struct ast_wdt_priv *priv = dev_get_priv(dev);
+	ulong driver_data = dev_get_driver_data(dev);
 
 	writel((u32) timeout, &priv->regs->counter_reload_val);
 	
 	writel(WDT_COUNTER_RESTART_VAL, &priv->regs->counter_restart);
 
-	writel(WDT_CTRL_EN | WDT_CTRL_RESET, &priv->regs->ctrl);
+	if (driver_data == WDT_AST2600) {
+		writel(WDT_CTRL_EN | WDT_CTRL_RESET |
+		       WDT_CTRL_WDT_RST_BY_SOC_RST, &priv->regs->ctrl);
+	} else {
+		writel(WDT_CTRL_EN | WDT_CTRL_RESET, &priv->regs->ctrl);
+	}
 
 	return 0;
 }
@@ -115,12 +122,15 @@ static int ast_wdt_stop(struct udevice *dev)
 
 	clrbits_le32(&priv->regs->ctrl, WDT_CTRL_EN);
 
+#if !defined(CONFIG_TARGET_AST2600_INTEL)
 	if(driver_data == WDT_AST2600) {
 		writel(0x030f1ff1, &priv->regs->reset_mask1);
 		writel(0x3fffff1, &priv->regs->reset_mask2);
-	} else 
+	} else {
 		writel(WDT_RESET_DEFAULT, &priv->regs->reset_mask1);
-	
+	}
+#endif
+
 	return 0;
 }
 
@@ -168,7 +178,9 @@ static const struct wdt_ops ast_wdt_ops = {
 static int ast_wdt_probe(struct udevice *dev)
 {
 	debug("%s() wdt%u\n", __func__, dev->seq);
+#if !defined(CONFIG_TARGET_AST2600_INTEL)
 	ast_wdt_stop(dev);
+#endif
 
 	return 0;
 }
diff --git a/include/configs/aspeed-common.h b/include/configs/aspeed-common.h
index 70590067dbcf..0eaf76b50b39 100644
--- a/include/configs/aspeed-common.h
+++ b/include/configs/aspeed-common.h
@@ -20,6 +20,8 @@
 
 #define CONFIG_STANDALONE_LOAD_ADDR 0x83000000
 
+#define CONFIG_HW_WATCHDOG
+
 /* Misc CPU related */
 #define CONFIG_CMDLINE_TAG
 #define CONFIG_SETUP_MEMORY_TAGS
-- 
2.17.1