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
93
94
95
|
/*
* DaVinci timer subsystem
*
* Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com>
*
* 2007 (c) MontaVista Software, Inc. This file is licensed under
* the terms of the GNU General Public License version 2. This program
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
#include <common.h>
#include <io.h>
#include <mach/time.h>
/* Timer register offsets */
#define PID12 0x0
#define TIM12 0x10
#define TIM34 0x14
#define PRD12 0x18
#define PRD34 0x1c
#define TCR 0x20
#define TGCR 0x24
#define WDTCR 0x28
/* Timer register bitfields */
#define TCR_ENAMODE_DISABLE 0x0
#define TCR_ENAMODE_ONESHOT 0x1
#define TCR_ENAMODE_PERIODIC 0x2
#define TCR_ENAMODE_MASK 0x3
#define TGCR_TIMMODE_SHIFT 2
#define TGCR_TIMMODE_64BIT_GP 0x0
#define TGCR_TIMMODE_32BIT_UNCHAINED 0x1
#define TGCR_TIMMODE_64BIT_WDOG 0x2
#define TGCR_TIMMODE_32BIT_CHAINED 0x3
#define TGCR_TIM12RS_SHIFT 0
#define TGCR_TIM34RS_SHIFT 1
#define TGCR_RESET 0x0
#define TGCR_UNRESET 0x1
#define TGCR_RESET_MASK 0x3
#define WDTCR_WDEN_SHIFT 14
#define WDTCR_WDEN_DISABLE 0x0
#define WDTCR_WDEN_ENABLE 0x1
#define WDTCR_WDKEY_SHIFT 16
#define WDTCR_WDKEY_SEQ0 0xa5c6
#define WDTCR_WDKEY_SEQ1 0xda7e
/* reset board using watchdog timer */
void __noreturn reset_cpu(ulong addr)
{
u32 tgcr, wdtcr;
void __iomem *base;
base = IOMEM(DAVINCI_WDOG_BASE);
/* disable, internal clock source */
__raw_writel(0, base + TCR);
/* reset timer, set mode to 64-bit watchdog, and unreset */
tgcr = 0;
__raw_writel(tgcr, base + TGCR);
tgcr = TGCR_TIMMODE_64BIT_WDOG << TGCR_TIMMODE_SHIFT;
tgcr |= (TGCR_UNRESET << TGCR_TIM12RS_SHIFT) |
(TGCR_UNRESET << TGCR_TIM34RS_SHIFT);
__raw_writel(tgcr, base + TGCR);
/* clear counter and period regs */
__raw_writel(0, base + TIM12);
__raw_writel(0, base + TIM34);
__raw_writel(0, base + PRD12);
__raw_writel(0, base + PRD34);
/* put watchdog in pre-active state */
wdtcr = __raw_readl(base + WDTCR);
wdtcr = (WDTCR_WDKEY_SEQ0 << WDTCR_WDKEY_SHIFT) |
(WDTCR_WDEN_ENABLE << WDTCR_WDEN_SHIFT);
__raw_writel(wdtcr, base + WDTCR);
/* put watchdog in active state */
wdtcr = (WDTCR_WDKEY_SEQ1 << WDTCR_WDKEY_SHIFT) |
(WDTCR_WDEN_ENABLE << WDTCR_WDEN_SHIFT);
__raw_writel(wdtcr, base + WDTCR);
/* write an invalid value to the WDKEY field to trigger
* a watchdog reset */
wdtcr = 0x00004000;
__raw_writel(wdtcr, base + WDTCR);
unreachable();
}
EXPORT_SYMBOL(reset_cpu);
|