watchdog/denali: Adding DesignWare watchdog driver support
[platform/kernel/u-boot.git] / drivers / watchdog / designware_wdt.c
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