blob: 79adad0c8e202a7ca24a3a9918fd5d0fc1816538 [file] [log] [blame]
#include "com_type.h"
#include "io.h"
#include "Galois_memmap.h"
#include "global.h"
#include "apbRegBase.h"
#include "debug.h"
#include "apb_watchdog.h"
#define CONFIG_DW_WDT_BASE 0xF7E80400
#define SOC_CHIP_CTRL_REG_BASE 0xF7EA0000 //MEMMAP_CHIP_CTRL_REG_BASE
#define CONFIG_DW_WDT_CLOCK_KHZ 25000
#define SYSTEM_RESET_MODE 0
#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_CRR_RESTART_VAL 0x76
#define DW_WDT_CR_RPL_OFFSET 0x02
#define DW_WDT_CR_RPL_MASK 0x07
#define DW_WDT_CR_RPL_PCLK_8 0x02
static void berlin_dw_wdt_set_rspmode(int mode)
{
unsigned int reg = readl(CONFIG_DW_WDT_BASE + DW_WDT_CR);
if (mode)
reg |= (1 << DW_WDT_CR_RMOD_OFFSET);
else
reg &= ~(1 << DW_WDT_CR_RMOD_OFFSET);
writel(reg, CONFIG_DW_WDT_BASE + DW_WDT_CR);
}
static void berlin_dw_wdt_set_rpl(unsigned int rpl)
{
unsigned int reg = readl(CONFIG_DW_WDT_BASE + DW_WDT_CR);
reg &= ~(DW_WDT_CR_RPL_MASK << DW_WDT_CR_RPL_OFFSET);
reg |= (rpl << DW_WDT_CR_RPL_OFFSET);
writel(reg, CONFIG_DW_WDT_BASE + DW_WDT_CR);
}
static inline int log_2_n_round_up(unsigned int n)
{
int log2n = -1;
unsigned int temp = n;
while (temp) {
log2n++;
temp >>= 1;
}
if (n & (n - 1))
return log2n + 1; /* not power of 2 - round up */
else
return log2n; /* power of 2 */
}
/*
* Set the watchdog time interval.
* Counter is 32 bit.
*/
static int berlin_dw_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 berlin_dw_wdt_init(void)
{
unsigned int wdt_mask;
#define RA_Gbl_WDTSysRstMask 0x0484
//Gbl + 0x0484 WDTSysRstMask
wdt_mask = readl(SOC_CHIP_CTRL_REG_BASE + RA_Gbl_WDTSysRstMask);
//Clear bit0 for wdt0 mask, bit1 for wdt1, bit2 for wdt2
wdt_mask &= ~(1<<0);
writel(wdt_mask, SOC_CHIP_CTRL_REG_BASE + RA_Gbl_WDTSysRstMask);
//interrupt mode, and reset signal pulse repeat 8 pclk cycles
berlin_dw_wdt_set_rspmode(SYSTEM_RESET_MODE);
berlin_dw_wdt_set_rpl(DW_WDT_CR_RPL_PCLK_8);
berlin_dw_wdt_settimeout(0); // 2-3ms
}
static void berlin_dw_wdt_enable(void)
{
unsigned int reg = readl(CONFIG_DW_WDT_BASE + DW_WDT_CR);
reg |= 0x1 << DW_WDT_CR_EN_OFFSET;
writel(reg, CONFIG_DW_WDT_BASE + DW_WDT_CR);
}
static unsigned int berlin_dw_wdt_is_enabled(void)
{
unsigned long val;
val = readl((CONFIG_DW_WDT_BASE + DW_WDT_CR));
return val & 0x1;
}
static void berlin_dw_wdt_restart(void)
{
if (berlin_dw_wdt_is_enabled())
/* restart the watchdog counter */
writel(DW_WDT_CRR_RESTART_VAL,
(CONFIG_DW_WDT_BASE + DW_WDT_CRR));
}
void reset_soc(void)
{
berlin_dw_wdt_init();
berlin_dw_wdt_enable();
berlin_dw_wdt_restart();
while (1)
/*nothing*/;
}