blob: a69eee4557b7037cc94ef1e244ad5ddf69ad5a72 [file] [log] [blame] [edit]
/*
* Copyright (c) 2020 The Fuchsia Authors
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <common.h>
#include <dm.h>
#include <errno.h>
#include <fdtdec.h>
#include <wdt.h>
#include <asm/io.h>
#include <asm/arch/clock.h>
#define WDT_CTRL_REG 0x0
#define WDT_TCNT_REG 0x8
#define WDT_RSET_REG 0xc
#define BIT(n) (1 << (n))
#define WDT_CTRL_CLKDIV_EN BIT(25)
#define WDT_CTRL_CLK_EN BIT(24)
#define WDT_CTRL_EE_RESET BIT(21)
#define WDT_CTRL_EN BIT(18)
#define WDT_CTRL_DIV_MASK (BIT(18) - 1)
#define WDT_TCNT_SETUP_MASK (BIT(16) - 1)
#define WDT_TCNT_CNT_SHIFT (16)
#define DEFAULT_TIMEOUT 1
static const fdt_addr_t reg_base = 0xffd0f0d0;
static const unsigned int rate = 24000000;
int wdt_reset(void)
{
writel(0, reg_base + WDT_RSET_REG);
return 0;
}
int wdt_set_timeout(unsigned long long timeout)
{
unsigned long long tcnt = timeout * 1000;
if (tcnt > WDT_TCNT_SETUP_MASK)
tcnt = WDT_TCNT_SETUP_MASK;
wdt_reset();
writel(tcnt, reg_base + WDT_TCNT_REG);
return 0;
}
int wdt_start(unsigned long long timeout)
{
wdt_set_timeout(timeout);
setbits_le32(reg_base + WDT_CTRL_REG, WDT_CTRL_EN);
return 0;
}
int wdt_stop(void)
{
clrbits_le32(reg_base + WDT_CTRL_REG, WDT_CTRL_EN);
return 0;
}
int wdt_init(void)
{
writel(((rate / 1000) & WDT_CTRL_DIV_MASK) | WDT_CTRL_EE_RESET |
WDT_CTRL_CLK_EN | WDT_CTRL_CLKDIV_EN,
reg_base + WDT_CTRL_REG);
wdt_set_timeout(DEFAULT_TIMEOUT);
wdt_stop();
return 0;
}