xref: /rk3399_rockchip-uboot/drivers/watchdog/at91sam9_wdt.c (revision e1cc4d31f889428a4ca73120951389c756404184)
1843a2654SJean-Christophe PLAGNIOL-VILLARD /*
2843a2654SJean-Christophe PLAGNIOL-VILLARD  * [origin: Linux kernel drivers/watchdog/at91sam9_wdt.c]
3843a2654SJean-Christophe PLAGNIOL-VILLARD  *
4843a2654SJean-Christophe PLAGNIOL-VILLARD  * Watchdog driver for Atmel AT91SAM9x processors.
5843a2654SJean-Christophe PLAGNIOL-VILLARD  *
6843a2654SJean-Christophe PLAGNIOL-VILLARD  * Copyright (C) 2008 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
7843a2654SJean-Christophe PLAGNIOL-VILLARD  * Copyright (C) 2008 Renaud CERRATO r.cerrato@til-technologies.fr
8843a2654SJean-Christophe PLAGNIOL-VILLARD  *
91a459660SWolfgang Denk  * SPDX-License-Identifier:	GPL-2.0+
10843a2654SJean-Christophe PLAGNIOL-VILLARD  */
11843a2654SJean-Christophe PLAGNIOL-VILLARD 
12843a2654SJean-Christophe PLAGNIOL-VILLARD /*
13843a2654SJean-Christophe PLAGNIOL-VILLARD  * The Watchdog Timer Mode Register can be only written to once. If the
14843a2654SJean-Christophe PLAGNIOL-VILLARD  * timeout need to be set from U-Boot, be sure that the bootstrap doesn't
15843a2654SJean-Christophe PLAGNIOL-VILLARD  * write to this register. Inform Linux to it too
16843a2654SJean-Christophe PLAGNIOL-VILLARD  */
17843a2654SJean-Christophe PLAGNIOL-VILLARD 
18843a2654SJean-Christophe PLAGNIOL-VILLARD #include <common.h>
19843a2654SJean-Christophe PLAGNIOL-VILLARD #include <watchdog.h>
20843a2654SJean-Christophe PLAGNIOL-VILLARD #include <asm/arch/hardware.h>
217f6ed7ffSReinhard Meyer #include <asm/io.h>
22843a2654SJean-Christophe PLAGNIOL-VILLARD #include <asm/arch/at91_wdt.h>
23843a2654SJean-Christophe PLAGNIOL-VILLARD 
24843a2654SJean-Christophe PLAGNIOL-VILLARD /*
25843a2654SJean-Christophe PLAGNIOL-VILLARD  * AT91SAM9 watchdog runs a 12bit counter @ 256Hz,
26843a2654SJean-Christophe PLAGNIOL-VILLARD  * use this to convert a watchdog
27843a2654SJean-Christophe PLAGNIOL-VILLARD  * value from/to milliseconds.
28843a2654SJean-Christophe PLAGNIOL-VILLARD  */
29843a2654SJean-Christophe PLAGNIOL-VILLARD #define ms_to_ticks(t)	(((t << 8) / 1000) - 1)
30843a2654SJean-Christophe PLAGNIOL-VILLARD #define ticks_to_ms(t)	(((t + 1) * 1000) >> 8)
31843a2654SJean-Christophe PLAGNIOL-VILLARD 
32843a2654SJean-Christophe PLAGNIOL-VILLARD /* Hardware timeout in seconds */
33*7bae0d6fSHeiko Schocher #if !defined(CONFIG_AT91_HW_WDT_TIMEOUT)
34843a2654SJean-Christophe PLAGNIOL-VILLARD #define WDT_HW_TIMEOUT 2
35*7bae0d6fSHeiko Schocher #else
36*7bae0d6fSHeiko Schocher #define WDT_HW_TIMEOUT CONFIG_AT91_HW_WDT_TIMEOUT
37*7bae0d6fSHeiko Schocher #endif
38843a2654SJean-Christophe PLAGNIOL-VILLARD 
39843a2654SJean-Christophe PLAGNIOL-VILLARD /*
40843a2654SJean-Christophe PLAGNIOL-VILLARD  * Set the watchdog time interval in 1/256Hz (write-once)
41843a2654SJean-Christophe PLAGNIOL-VILLARD  * Counter is 12 bit.
42843a2654SJean-Christophe PLAGNIOL-VILLARD  */
at91_wdt_settimeout(unsigned int timeout)43843a2654SJean-Christophe PLAGNIOL-VILLARD static int at91_wdt_settimeout(unsigned int timeout)
44843a2654SJean-Christophe PLAGNIOL-VILLARD {
45843a2654SJean-Christophe PLAGNIOL-VILLARD 	unsigned int reg;
46372f2783SReinhard Meyer 	at91_wdt_t *wd = (at91_wdt_t *) ATMEL_BASE_WDT;
47843a2654SJean-Christophe PLAGNIOL-VILLARD 
48843a2654SJean-Christophe PLAGNIOL-VILLARD 	/* Check if disabled */
49f936aa05SAchim Ehrlich 	if (readl(&wd->mr) & AT91_WDT_MR_WDDIS) {
50843a2654SJean-Christophe PLAGNIOL-VILLARD 		printf("sorry, watchdog is disabled\n");
51843a2654SJean-Christophe PLAGNIOL-VILLARD 		return -1;
52843a2654SJean-Christophe PLAGNIOL-VILLARD 	}
53843a2654SJean-Christophe PLAGNIOL-VILLARD 
54843a2654SJean-Christophe PLAGNIOL-VILLARD 	/*
55843a2654SJean-Christophe PLAGNIOL-VILLARD 	 * All counting occurs at SLOW_CLOCK / 128 = 256 Hz
56843a2654SJean-Christophe PLAGNIOL-VILLARD 	 *
57843a2654SJean-Christophe PLAGNIOL-VILLARD 	 * Since WDV is a 12-bit counter, the maximum period is
58843a2654SJean-Christophe PLAGNIOL-VILLARD 	 * 4096 / 256 = 16 seconds.
59843a2654SJean-Christophe PLAGNIOL-VILLARD 	 */
60f936aa05SAchim Ehrlich 
61f936aa05SAchim Ehrlich 	reg = AT91_WDT_MR_WDRSTEN		/* causes watchdog reset */
62f936aa05SAchim Ehrlich 		| AT91_WDT_MR_WDDBGHLT		/* disabled in debug mode */
63f936aa05SAchim Ehrlich 		| AT91_WDT_MR_WDD(0xfff)	/* restart at any time */
64f936aa05SAchim Ehrlich 		| AT91_WDT_MR_WDV(timeout);	/* timer value */
65f936aa05SAchim Ehrlich 
66f936aa05SAchim Ehrlich 	writel(reg, &wd->mr);
67843a2654SJean-Christophe PLAGNIOL-VILLARD 
68843a2654SJean-Christophe PLAGNIOL-VILLARD 	return 0;
69843a2654SJean-Christophe PLAGNIOL-VILLARD }
70843a2654SJean-Christophe PLAGNIOL-VILLARD 
hw_watchdog_reset(void)71843a2654SJean-Christophe PLAGNIOL-VILLARD void hw_watchdog_reset(void)
72843a2654SJean-Christophe PLAGNIOL-VILLARD {
73372f2783SReinhard Meyer 	at91_wdt_t *wd = (at91_wdt_t *) ATMEL_BASE_WDT;
74f936aa05SAchim Ehrlich 	writel(AT91_WDT_CR_WDRSTT | AT91_WDT_CR_KEY, &wd->cr);
75843a2654SJean-Christophe PLAGNIOL-VILLARD }
76843a2654SJean-Christophe PLAGNIOL-VILLARD 
hw_watchdog_init(void)77843a2654SJean-Christophe PLAGNIOL-VILLARD void hw_watchdog_init(void)
78843a2654SJean-Christophe PLAGNIOL-VILLARD {
79843a2654SJean-Christophe PLAGNIOL-VILLARD 	/* 16 seconds timer, resets enabled */
80843a2654SJean-Christophe PLAGNIOL-VILLARD 	at91_wdt_settimeout(ms_to_ticks(WDT_HW_TIMEOUT * 1000));
81843a2654SJean-Christophe PLAGNIOL-VILLARD }
82