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