xref: /openbmc/u-boot/drivers/watchdog/designware_wdt.c (revision 83d290c56fab2d38cd1ab4c4cc7099559c1d5046)
1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2d8c67dc6SChin Liang See /*
3d8c67dc6SChin Liang See  * Copyright (C) 2013 Altera Corporation <www.altera.com>
4d8c67dc6SChin Liang See  */
5d8c67dc6SChin Liang See 
6d8c67dc6SChin Liang See #include <common.h>
7d8c67dc6SChin Liang See #include <watchdog.h>
8d8c67dc6SChin Liang See #include <asm/io.h>
9d8c67dc6SChin Liang See #include <asm/utils.h>
10d8c67dc6SChin Liang See 
11d8c67dc6SChin Liang See #define DW_WDT_CR	0x00
12d8c67dc6SChin Liang See #define DW_WDT_TORR	0x04
13d8c67dc6SChin Liang See #define DW_WDT_CRR	0x0C
14d8c67dc6SChin Liang See 
15d8c67dc6SChin Liang See #define DW_WDT_CR_EN_OFFSET	0x00
16d8c67dc6SChin Liang See #define DW_WDT_CR_RMOD_OFFSET	0x01
17d8c67dc6SChin Liang See #define DW_WDT_CR_RMOD_VAL	0x00
18d8c67dc6SChin Liang See #define DW_WDT_CRR_RESTART_VAL	0x76
19d8c67dc6SChin Liang See 
20d8c67dc6SChin Liang See /*
21d8c67dc6SChin Liang See  * Set the watchdog time interval.
22d8c67dc6SChin Liang See  * Counter is 32 bit.
23d8c67dc6SChin Liang See  */
designware_wdt_settimeout(unsigned int timeout)24d8c67dc6SChin Liang See static int designware_wdt_settimeout(unsigned int timeout)
25d8c67dc6SChin Liang See {
26d8c67dc6SChin Liang See 	signed int i;
27d8c67dc6SChin Liang See 
28d8c67dc6SChin Liang See 	/* calculate the timeout range value */
29d8c67dc6SChin Liang See 	i = (log_2_n_round_up(timeout * CONFIG_DW_WDT_CLOCK_KHZ)) - 16;
30d8c67dc6SChin Liang See 	if (i > 15)
31d8c67dc6SChin Liang See 		i = 15;
32d8c67dc6SChin Liang See 	if (i < 0)
33d8c67dc6SChin Liang See 		i = 0;
34d8c67dc6SChin Liang See 
35d8c67dc6SChin Liang See 	writel((i | (i << 4)), (CONFIG_DW_WDT_BASE + DW_WDT_TORR));
36d8c67dc6SChin Liang See 	return 0;
37d8c67dc6SChin Liang See }
38d8c67dc6SChin Liang See 
designware_wdt_enable(void)39d8c67dc6SChin Liang See static void designware_wdt_enable(void)
40d8c67dc6SChin Liang See {
41d8c67dc6SChin Liang See 	writel(((DW_WDT_CR_RMOD_VAL << DW_WDT_CR_RMOD_OFFSET) |
42d8c67dc6SChin Liang See 	      (0x1 << DW_WDT_CR_EN_OFFSET)),
43d8c67dc6SChin Liang See 	      (CONFIG_DW_WDT_BASE + DW_WDT_CR));
44d8c67dc6SChin Liang See }
45d8c67dc6SChin Liang See 
designware_wdt_is_enabled(void)46d8c67dc6SChin Liang See static unsigned int designware_wdt_is_enabled(void)
47d8c67dc6SChin Liang See {
48d8c67dc6SChin Liang See 	unsigned long val;
49d8c67dc6SChin Liang See 	val = readl((CONFIG_DW_WDT_BASE + DW_WDT_CR));
50d8c67dc6SChin Liang See 	return val & 0x1;
51d8c67dc6SChin Liang See }
52d8c67dc6SChin Liang See 
53d8c67dc6SChin Liang See #if defined(CONFIG_HW_WATCHDOG)
hw_watchdog_reset(void)54d8c67dc6SChin Liang See void hw_watchdog_reset(void)
55d8c67dc6SChin Liang See {
56d8c67dc6SChin Liang See 	if (designware_wdt_is_enabled())
57d8c67dc6SChin Liang See 		/* restart the watchdog counter */
58d8c67dc6SChin Liang See 		writel(DW_WDT_CRR_RESTART_VAL,
59d8c67dc6SChin Liang See 		       (CONFIG_DW_WDT_BASE + DW_WDT_CRR));
60d8c67dc6SChin Liang See }
61d8c67dc6SChin Liang See 
hw_watchdog_init(void)62d8c67dc6SChin Liang See void hw_watchdog_init(void)
63d8c67dc6SChin Liang See {
64d8c67dc6SChin Liang See 	/* reset to disable the watchdog */
65d8c67dc6SChin Liang See 	hw_watchdog_reset();
66d8c67dc6SChin Liang See 	/* set timer in miliseconds */
67ea926511SAndy Shevchenko 	designware_wdt_settimeout(CONFIG_WATCHDOG_TIMEOUT_MSECS);
68d8c67dc6SChin Liang See 	/* enable the watchdog */
69d8c67dc6SChin Liang See 	designware_wdt_enable();
70d8c67dc6SChin Liang See 	/* reset the watchdog */
71d8c67dc6SChin Liang See 	hw_watchdog_reset();
72d8c67dc6SChin Liang See }
73d8c67dc6SChin Liang See #endif
74