1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2013 Altera Corporation <www.altera.com>
4  */
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  */
24 static 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 
39 static 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 
46 static 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)
54 void 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 
62 void hw_watchdog_init(void)
63 {
64 	/* reset to disable the watchdog */
65 	hw_watchdog_reset();
66 	/* set timer in miliseconds */
67 	designware_wdt_settimeout(CONFIG_WATCHDOG_TIMEOUT_MSECS);
68 	/* enable the watchdog */
69 	designware_wdt_enable();
70 	/* reset the watchdog */
71 	hw_watchdog_reset();
72 }
73 #endif
74