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