]>
Commit | Line | Data |
---|---|---|
843a2654 JCPV |
1 | /* |
2 | * [origin: Linux kernel drivers/watchdog/at91sam9_wdt.c] | |
3 | * | |
4 | * Watchdog driver for Atmel AT91SAM9x processors. | |
5 | * | |
6 | * Copyright (C) 2008 Jean-Christophe PLAGNIOL-VILLARD <[email protected]> | |
7 | * Copyright (C) 2008 Renaud CERRATO [email protected] | |
8 | * | |
1a459660 | 9 | * SPDX-License-Identifier: GPL-2.0+ |
843a2654 JCPV |
10 | */ |
11 | ||
12 | /* | |
13 | * The Watchdog Timer Mode Register can be only written to once. If the | |
14 | * timeout need to be set from U-Boot, be sure that the bootstrap doesn't | |
15 | * write to this register. Inform Linux to it too | |
16 | */ | |
17 | ||
18 | #include <common.h> | |
19 | #include <watchdog.h> | |
20 | #include <asm/arch/hardware.h> | |
7f6ed7ff | 21 | #include <asm/io.h> |
843a2654 JCPV |
22 | #include <asm/arch/at91_wdt.h> |
23 | ||
24 | /* | |
25 | * AT91SAM9 watchdog runs a 12bit counter @ 256Hz, | |
26 | * use this to convert a watchdog | |
27 | * value from/to milliseconds. | |
28 | */ | |
29 | #define ms_to_ticks(t) (((t << 8) / 1000) - 1) | |
30 | #define ticks_to_ms(t) (((t + 1) * 1000) >> 8) | |
31 | ||
32 | /* Hardware timeout in seconds */ | |
7bae0d6f | 33 | #if !defined(CONFIG_AT91_HW_WDT_TIMEOUT) |
843a2654 | 34 | #define WDT_HW_TIMEOUT 2 |
7bae0d6f HS |
35 | #else |
36 | #define WDT_HW_TIMEOUT CONFIG_AT91_HW_WDT_TIMEOUT | |
37 | #endif | |
843a2654 JCPV |
38 | |
39 | /* | |
40 | * Set the watchdog time interval in 1/256Hz (write-once) | |
41 | * Counter is 12 bit. | |
42 | */ | |
43 | static int at91_wdt_settimeout(unsigned int timeout) | |
44 | { | |
45 | unsigned int reg; | |
372f2783 | 46 | at91_wdt_t *wd = (at91_wdt_t *) ATMEL_BASE_WDT; |
843a2654 JCPV |
47 | |
48 | /* Check if disabled */ | |
f936aa05 | 49 | if (readl(&wd->mr) & AT91_WDT_MR_WDDIS) { |
843a2654 JCPV |
50 | printf("sorry, watchdog is disabled\n"); |
51 | return -1; | |
52 | } | |
53 | ||
54 | /* | |
55 | * All counting occurs at SLOW_CLOCK / 128 = 256 Hz | |
56 | * | |
57 | * Since WDV is a 12-bit counter, the maximum period is | |
58 | * 4096 / 256 = 16 seconds. | |
59 | */ | |
f936aa05 AE |
60 | |
61 | reg = AT91_WDT_MR_WDRSTEN /* causes watchdog reset */ | |
62 | | AT91_WDT_MR_WDDBGHLT /* disabled in debug mode */ | |
63 | | AT91_WDT_MR_WDD(0xfff) /* restart at any time */ | |
64 | | AT91_WDT_MR_WDV(timeout); /* timer value */ | |
65 | ||
66 | writel(reg, &wd->mr); | |
843a2654 JCPV |
67 | |
68 | return 0; | |
69 | } | |
70 | ||
71 | void hw_watchdog_reset(void) | |
72 | { | |
372f2783 | 73 | at91_wdt_t *wd = (at91_wdt_t *) ATMEL_BASE_WDT; |
f936aa05 | 74 | writel(AT91_WDT_CR_WDRSTT | AT91_WDT_CR_KEY, &wd->cr); |
843a2654 JCPV |
75 | } |
76 | ||
77 | void hw_watchdog_init(void) | |
78 | { | |
79 | /* 16 seconds timer, resets enabled */ | |
80 | at91_wdt_settimeout(ms_to_ticks(WDT_HW_TIMEOUT * 1000)); | |
81 | } |