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*4882a593Smuzhiyunstatic 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*4882a593Smuzhiyunstatic 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*4882a593Smuzhiyunstatic 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*4882a593Smuzhiyunvoid 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*4882a593Smuzhiyunvoid 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