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
|