blob: c668567c66330c49e0b41af9fd4ac1d9e792f565 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Chin Liang See9d800092014-06-10 01:10:21 -05002/*
3 * Copyright (C) 2013 Altera Corporation <www.altera.com>
Chin Liang See9d800092014-06-10 01:10:21 -05004 */
5
6#include <common.h>
7#include <watchdog.h>
8#include <asm/io.h>
9#include <asm/utils.h>
10
11#define DW_WDT_CR 0x00
12#define DW_WDT_TORR 0x04
13#define DW_WDT_CRR 0x0C
14
15#define DW_WDT_CR_EN_OFFSET 0x00
16#define DW_WDT_CR_RMOD_OFFSET 0x01
17#define DW_WDT_CR_RMOD_VAL 0x00
18#define DW_WDT_CRR_RESTART_VAL 0x76
19
20/*
21 * Set the watchdog time interval.
22 * Counter is 32 bit.
23 */
24static int designware_wdt_settimeout(unsigned int timeout)
25{
26 signed int i;
27
28 /* calculate the timeout range value */
29 i = (log_2_n_round_up(timeout * CONFIG_DW_WDT_CLOCK_KHZ)) - 16;
30 if (i > 15)
31 i = 15;
32 if (i < 0)
33 i = 0;
34
35 writel((i | (i << 4)), (CONFIG_DW_WDT_BASE + DW_WDT_TORR));
36 return 0;
37}
38
39static void designware_wdt_enable(void)
40{
41 writel(((DW_WDT_CR_RMOD_VAL << DW_WDT_CR_RMOD_OFFSET) |
42 (0x1 << DW_WDT_CR_EN_OFFSET)),
43 (CONFIG_DW_WDT_BASE + DW_WDT_CR));
44}
45
46static unsigned int designware_wdt_is_enabled(void)
47{
48 unsigned long val;
49 val = readl((CONFIG_DW_WDT_BASE + DW_WDT_CR));
50 return val & 0x1;
51}
52
53#if defined(CONFIG_HW_WATCHDOG)
54void hw_watchdog_reset(void)
55{
56 if (designware_wdt_is_enabled())
57 /* restart the watchdog counter */
58 writel(DW_WDT_CRR_RESTART_VAL,
59 (CONFIG_DW_WDT_BASE + DW_WDT_CRR));
60}
61
62void hw_watchdog_init(void)
63{
64 /* reset to disable the watchdog */
65 hw_watchdog_reset();
66 /* set timer in miliseconds */
Andy Shevchenko3c08d312017-07-05 20:44:08 +030067 designware_wdt_settimeout(CONFIG_WATCHDOG_TIMEOUT_MSECS);
Chin Liang See9d800092014-06-10 01:10:21 -050068 /* enable the watchdog */
69 designware_wdt_enable();
70 /* reset the watchdog */
71 hw_watchdog_reset();
72}
73#endif