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