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