]>
Commit | Line | Data |
---|---|---|
8f8a12d1 FB |
1 | /* |
2 | * Copyright (c) 2017 Intel Corporation | |
3 | * | |
4 | * SPDX-License-Identifier: GPL-2.0+ | |
5 | */ | |
6 | #include <common.h> | |
7 | #include <watchdog.h> | |
8 | #include <asm/scu.h> | |
9 | ||
10 | /* Hardware timeout in seconds */ | |
11 | #define WDT_PRETIMEOUT 15 | |
12 | #define WDT_TIMEOUT_MIN (1 + WDT_PRETIMEOUT) | |
13 | #define WDT_TIMEOUT_MAX 170 | |
14 | #define WDT_DEFAULT_TIMEOUT 90 | |
15 | ||
16 | #ifndef CONFIG_WATCHDOG_TIMEOUT_MSECS | |
17 | #define WATCHDOG_HEARTBEAT 60000 | |
18 | #else | |
19 | #define WATCHDOG_HEARTBEAT CONFIG_WATCHDOG_TIMEOUT_MSECS | |
20 | #endif | |
21 | ||
22 | enum { | |
23 | SCU_WATCHDOG_START = 0, | |
24 | SCU_WATCHDOG_STOP = 1, | |
25 | SCU_WATCHDOG_KEEPALIVE = 2, | |
26 | SCU_WATCHDOG_SET_ACTION_ON_TIMEOUT = 3, | |
27 | }; | |
28 | ||
29 | void hw_watchdog_reset(void) | |
30 | { | |
31 | static unsigned long last; | |
32 | unsigned long now; | |
33 | ||
34 | if (gd->timer) | |
35 | now = timer_get_us(); | |
36 | else | |
37 | now = rdtsc() / 1000; | |
38 | ||
39 | /* Do not flood SCU */ | |
40 | if (last > now) | |
41 | last = 0; | |
42 | ||
43 | if (unlikely((now - last) > (WDT_PRETIMEOUT / 2) * 1000000)) { | |
44 | last = now; | |
45 | scu_ipc_simple_command(IPCMSG_WATCHDOG_TIMER, SCU_WATCHDOG_KEEPALIVE); | |
46 | } | |
47 | } | |
48 | ||
49 | int hw_watchdog_disable(void) | |
50 | { | |
51 | return scu_ipc_simple_command(IPCMSG_WATCHDOG_TIMER, SCU_WATCHDOG_STOP); | |
52 | } | |
53 | ||
54 | void hw_watchdog_init(void) | |
55 | { | |
56 | u32 timeout = WATCHDOG_HEARTBEAT / 1000; | |
57 | int in_size; | |
58 | struct ipc_wd_start { | |
59 | u32 pretimeout; | |
60 | u32 timeout; | |
61 | } ipc_wd_start = { timeout - WDT_PRETIMEOUT, timeout }; | |
62 | ||
63 | /* | |
64 | * SCU expects the input size for watchdog IPC | |
65 | * to be based on 4 bytes | |
66 | */ | |
67 | in_size = DIV_ROUND_UP(sizeof(ipc_wd_start), 4); | |
68 | ||
69 | scu_ipc_command(IPCMSG_WATCHDOG_TIMER, SCU_WATCHDOG_START, | |
70 | (u32 *)&ipc_wd_start, in_size, NULL, 0); | |
71 | } |