| /* |
| * Copyright (C) 2013 Altera Corporation <www.altera.com> |
| * |
| * SPDX-License-Identifier: GPL-2.0+ |
| */ |
| |
| #include <common.h> |
| #include <watchdog.h> |
| #include <asm/io.h> |
| #include <asm/utils.h> |
| |
| #define DW_WDT_CR 0x00 |
| #define DW_WDT_TORR 0x04 |
| #define DW_WDT_CRR 0x0C |
| |
| #define DW_WDT_CR_EN_OFFSET 0x00 |
| #define DW_WDT_CR_RMOD_OFFSET 0x01 |
| #define DW_WDT_CR_RMOD_VAL 0x00 |
| #define DW_WDT_CRR_RESTART_VAL 0x76 |
| |
| /* |
| * Set the watchdog time interval. |
| * Counter is 32 bit. |
| */ |
| static int designware_wdt_settimeout(unsigned int timeout) |
| { |
| signed int i; |
| |
| /* calculate the timeout range value */ |
| i = (log_2_n_round_up(timeout * CONFIG_DW_WDT_CLOCK_KHZ)) - 16; |
| if (i > 15) |
| i = 15; |
| if (i < 0) |
| i = 0; |
| |
| writel((i | (i << 4)), (CONFIG_DW_WDT_BASE + DW_WDT_TORR)); |
| return 0; |
| } |
| |
| static void designware_wdt_enable(void) |
| { |
| writel(((DW_WDT_CR_RMOD_VAL << DW_WDT_CR_RMOD_OFFSET) | |
| (0x1 << DW_WDT_CR_EN_OFFSET)), |
| (CONFIG_DW_WDT_BASE + DW_WDT_CR)); |
| } |
| |
| static unsigned int designware_wdt_is_enabled(void) |
| { |
| unsigned long val; |
| val = readl((CONFIG_DW_WDT_BASE + DW_WDT_CR)); |
| return val & 0x1; |
| } |
| |
| #if defined(CONFIG_HW_WATCHDOG) |
| void hw_watchdog_reset(void) |
| { |
| if (designware_wdt_is_enabled()) |
| /* restart the watchdog counter */ |
| writel(DW_WDT_CRR_RESTART_VAL, |
| (CONFIG_DW_WDT_BASE + DW_WDT_CRR)); |
| } |
| |
| void hw_watchdog_init(void) |
| { |
| /* reset to disable the watchdog */ |
| hw_watchdog_reset(); |
| /* set timer in miliseconds */ |
| designware_wdt_settimeout(CONFIG_HW_WATCHDOG_TIMEOUT_MS); |
| /* enable the watchdog */ |
| designware_wdt_enable(); |
| /* reset the watchdog */ |
| hw_watchdog_reset(); |
| } |
| #endif |