blob: d724c964ed29413a483d4fd26a93999e6d239942 [file] [log] [blame]
Heiko Schocher910a7222013-08-19 16:38:59 +02001/*
2 * omap_wdt.c
3 *
4 * (C) Copyright 2013
5 * Heiko Schocher, DENX Software Engineering, hs@denx.de.
6 *
7 * SPDX-License-Identifier: GPL-2.0
8 *
9 * Based on:
10 *
11 * Watchdog driver for the TI OMAP 16xx & 24xx/34xx 32KHz (non-secure) watchdog
12 *
13 * commit 2d991a164a61858012651e13c59521975504e260
14 * Author: Bill Pemberton <wfp5p@virginia.edu>
15 * Date: Mon Nov 19 13:21:41 2012 -0500
16 *
17 * watchdog: remove use of __devinit
18 *
19 * CONFIG_HOTPLUG is going away as an option so __devinit is no longer
20 * needed.
21 *
22 * Author: MontaVista Software, Inc.
23 * <gdavis@mvista.com> or <source@mvista.com>
24 *
25 * History:
26 *
27 * 20030527: George G. Davis <gdavis@mvista.com>
28 * Initially based on linux-2.4.19-rmk7-pxa1/drivers/char/sa1100_wdt.c
29 * (c) Copyright 2000 Oleg Drokin <green@crimea.edu>
30 * Based on SoftDog driver by Alan Cox <alan@lxorguk.ukuu.org.uk>
31 *
32 * Copyright (c) 2004 Texas Instruments.
33 * 1. Modified to support OMAP1610 32-KHz watchdog timer
34 * 2. Ported to 2.6 kernel
35 *
36 * Copyright (c) 2005 David Brownell
37 * Use the driver model and standard identifiers; handle bigger timeouts.
38 */
39
40#include <common.h>
41#include <watchdog.h>
42#include <asm/arch/hardware.h>
43#include <asm/io.h>
44#include <asm/processor.h>
45#include <asm/arch/cpu.h>
46
47/* Hardware timeout in seconds */
48#define WDT_HW_TIMEOUT 60
49
50static unsigned int wdt_trgr_pattern = 0x1234;
51
52void hw_watchdog_reset(void)
53{
54 struct wd_timer *wdt = (struct wd_timer *)WDT_BASE;
55
Ruslan Bilovol721656d2018-03-01 03:15:48 +020056 /*
57 * Somebody just triggered watchdog reset and write to WTGR register
58 * is in progress. It is resetting right now, no need to trigger it
59 * again
60 */
61 if ((readl(&wdt->wdtwwps)) & WDT_WWPS_PEND_WTGR)
62 return;
Heiko Schocher910a7222013-08-19 16:38:59 +020063
64 wdt_trgr_pattern = ~wdt_trgr_pattern;
65 writel(wdt_trgr_pattern, &wdt->wdtwtgr);
66
Ruslan Bilovol721656d2018-03-01 03:15:48 +020067 /*
68 * Don't wait for posted write to complete, i.e. don't check
69 * WDT_WWPS_PEND_WTGR bit in WWPS register. There is no writes to
70 * WTGR register outside of this func, and if entering it
71 * we see WDT_WWPS_PEND_WTGR bit set, it means watchdog reset
72 * was just triggered. This prevents us from wasting time in busy
73 * polling of WDT_WWPS_PEND_WTGR bit.
74 */
Heiko Schocher910a7222013-08-19 16:38:59 +020075}
76
77static int omap_wdt_set_timeout(unsigned int timeout)
78{
79 struct wd_timer *wdt = (struct wd_timer *)WDT_BASE;
80 u32 pre_margin = GET_WLDR_VAL(timeout);
81
82 /* just count up at 32 KHz */
83 while (readl(&wdt->wdtwwps) & WDT_WWPS_PEND_WLDR)
84 ;
85
86 writel(pre_margin, &wdt->wdtwldr);
87 while (readl(&wdt->wdtwwps) & WDT_WWPS_PEND_WLDR)
88 ;
89
90 return 0;
91}
92
Lukasz Majewskibdf8a422017-02-19 23:24:38 +010093void hw_watchdog_disable(void)
94{
95 struct wd_timer *wdt = (struct wd_timer *)WDT_BASE;
96
97 /*
98 * Disable watchdog
99 */
100 writel(0xAAAA, &wdt->wdtwspr);
101 while (readl(&wdt->wdtwwps) != 0x0)
102 ;
103 writel(0x5555, &wdt->wdtwspr);
104 while (readl(&wdt->wdtwwps) != 0x0)
105 ;
106}
107
Heiko Schocher910a7222013-08-19 16:38:59 +0200108void hw_watchdog_init(void)
109{
110 struct wd_timer *wdt = (struct wd_timer *)WDT_BASE;
111
Lukasz Majewskibdf8a422017-02-19 23:24:38 +0100112 /*
113 * Make sure the watchdog is disabled. This is unfortunately required
114 * because writing to various registers with the watchdog running has no
115 * effect.
116 */
117 hw_watchdog_disable();
118
Heiko Schocher910a7222013-08-19 16:38:59 +0200119 /* initialize prescaler */
120 while (readl(&wdt->wdtwwps) & WDT_WWPS_PEND_WCLR)
121 ;
122
123 writel(WDT_WCLR_PRE | (PTV << WDT_WCLR_PTV_OFF), &wdt->wdtwclr);
124 while (readl(&wdt->wdtwwps) & WDT_WWPS_PEND_WCLR)
125 ;
126
127 omap_wdt_set_timeout(WDT_HW_TIMEOUT);
128
129 /* Sequence to enable the watchdog */
130 writel(0xBBBB, &wdt->wdtwspr);
131 while ((readl(&wdt->wdtwwps)) & WDT_WWPS_PEND_WSPR)
132 ;
133
134 writel(0x4444, &wdt->wdtwspr);
135 while ((readl(&wdt->wdtwwps)) & WDT_WWPS_PEND_WSPR)
136 ;
137}