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-VILLARDstatic 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-VILLARDvoid 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-VILLARDvoid 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