blob: 3773a3b6efa0b8adfda1e144549c128447d6c35f [file] [log] [blame]
Varun Wadekar8dcb7372020-03-26 16:17:01 -07001/*
2 * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <debug.h>
8#include <mmio.h>
9#include <platform.h>
10
11/* Timer registers */
12#define TIMER_PTV U(0)
13 #define TIMER_EN_BIT BIT_32(31)
14 #define TIMER_PERIODIC_BIT BIT_32(30)
15#define TIMER_PCR U(0x4)
16 #define TIMER_PCR_INTR_BIT BIT_32(30)
17
18/* WDT registers */
19#define WDT_CFG U(0)
20 #define WDT_CFG_TMR_SRC U(0) /* for TMR0. */
21 #define WDT_CFG_PERIOD_BIT BIT_32(4)
22 #define WDT_CFG_INT_EN_BIT BIT_32(12)
23 #define WDT_CFG_SYS_RST_EN_BIT BIT_32(14)
24 #define WDT_CFG_PMC2CAR_RST_EN_BIT BIT_32(15)
25#define WDT_CMD U(8)
26 #define WDT_CMD_START_COUNTER_BIT BIT_32(0)
27 #define WDT_CMD_DISABLE_COUNTER_BIT BIT_32(1)
28#define WDT_UNLOCK U(0xC)
29 #define WDT_UNLOCK_PATTERN U(0xC45A)
30
31/* watchdog will fire after this timeout value is reached */
32#define WDT_TIMEOUT_SECONDS U(10)
33#define WDT_TIMEOUT_MULTIPLIER UL(125000)
34
35static inline void tegra194_wdt_write(uint32_t offset, uint32_t val)
36{
37 mmio_write_32(TEGRA194_WDT0_BASE + offset, val);
38}
39
40static inline uint32_t tegra194_wdt_read(uint32_t offset)
41{
42 return mmio_read_32(TEGRA194_WDT0_BASE + offset);
43}
44
45static inline void tegra194_tmr_write(uint32_t offset, uint32_t val)
46{
47 mmio_write_32(TEGRA194_TMR0_BASE + offset, val);
48}
49
50static inline uint32_t tegra194_tmr_read(uint32_t offset)
51{
52 return mmio_read_32(TEGRA194_TMR0_BASE + offset);
53}
54
55/*
56 * Start the watchdog timer
57 */
58void tftf_platform_watchdog_set(void)
59{
60 uint32_t val;
61
62 /* Clear pending interrupts first */
63 tegra194_tmr_write(TIMER_PCR, TIMER_PCR_INTR_BIT);
64
65 /*
66 * Normally, we would set the period to 1 second by writing 125000ul,
67 * but the watchdog system reset actually occurs on the 4th expiration
68 * of this counter, so we set the period to 1/4 of this amount.
69 */
70 val = (WDT_TIMEOUT_SECONDS * WDT_TIMEOUT_MULTIPLIER) / 4;
71 val |= (TIMER_EN_BIT | TIMER_PERIODIC_BIT);
72 tegra194_tmr_write(TIMER_PTV, val);
73
74 /*
75 * Set number of periods and start counter.
76 */
77 val = WDT_CFG_TMR_SRC | WDT_CFG_SYS_RST_EN_BIT |
78 WDT_CFG_PMC2CAR_RST_EN_BIT;
79 tegra194_wdt_write(WDT_CFG, val);
80 tegra194_wdt_write(WDT_CMD, WDT_CMD_START_COUNTER_BIT);
81}
82
83/*
84 * Stop the watchdog timer
85 */
86void tftf_platform_watchdog_reset(void)
87{
88 tegra194_tmr_write(TIMER_PCR, TIMER_PCR_INTR_BIT);
89 tegra194_wdt_write(WDT_UNLOCK, WDT_UNLOCK_PATTERN);
90 tegra194_wdt_write(WDT_CMD, WDT_CMD_DISABLE_COUNTER_BIT);
91 tegra194_tmr_write(TIMER_PTV, 0);
92}