| /* |
| * 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; |
| } |